将HTML5画布加载到Django中的PIL图像中

11 投票
4 回答
9968 浏览
提问于 2025-04-17 04:21

我正在尝试获取一个html5画布的内容,并把它传送到我的django服务器,在那里我会用PIL进行处理,然后保存为PNG格式。到目前为止,我的进展是这样的:

用户在HTML表单中点击“更新”按钮,画布的内容会通过canvas.toDataURL()方法转成数据,然后放入一个文本框,最后通过POST表单提交。最终这个过程会变得自动化,但现在还不是。

<input type="text" id="canvasData" name="canvasData"/>
<input type='button' value="update" onclick='jscript:updateData();'>
<canvas id="sketch"></canvas>
<script type="text/javascript">
    function jscript:updateData() {
        $('#canvasData')[0].value = $('canvas')[0].toDataURL();
    }
</script>

当canvasData被发送时,它的格式是'data:image/png;base64,iVBORw0KGgoAAAA...等等...='。接下来我在django中处理这个数据:

from PIL import Image
...
canvasData = request.POST.get('canvasData', '')
im = Image.somehowLoad(canvasData)
...
im.save('canvas.png')

现在我遇到了问题。我不知道怎么把这个base64编码的数据网址加载成PIL可以使用的图像格式。

谢谢!

补充:这是底部评论的代码:

>>> d
'data:image/png;base64,iVBORw0K'
>>> d.strip('data:image/png;base64,')
'VBORw0K'

4 个回答

1

在2019年,我用Python 3尝试了Acorn的回答,结果出现了一个错误:'str'对象没有'decode'这个属性。于是我查了一下资料,调整了一下代码,结果就成功了。下面是我调整后的代码:

from binascii import a2b_base64
import re

datauri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='

imgstr = re.search(r'base64,(.*)', datauri).group(1)

binary_data = a2b_base64(imgstr)

Out = open('image.png', 'wb')
Out.write(binary_data)
Out.close()
3

HTML:

<form action="" method="post">
    {% csrf_token %}
    <input type="hidden" name="width" value="">
    <input type="hidden" name="height" value="">
    <input type="hidden" name="image_data" value="">
</form>

Javascript:

function submit_pixels(canvas) {
    $('form input[name=image_data]').val(canvas.toDataURL("image/png"));
    $('form input[name=width]').val(canvas.width);
    $('form input[name=height]').val(canvas.height);
    $('form').submit();
}

Django的POST请求视图:

# in the module scope
from io import BytesIO
from PIL import Image
import re
import base64

# in your view function
image_data = request.POST['image_data']
image_width = int(request.POST['width'])
image_height = int(request.POST['height'])
image_data = re.sub("^data:image/png;base64,", "", image_data)
image_data = base64.b64decode(image_data)
image_data = BytesIO(image_data)
im = Image.open(image_data)
assert (image_width, image_height,) == im.size

在你的设置中增加最大POST大小(例如:大约20 MB):

# canvas data urls are large
DATA_UPLOAD_MAX_MEMORY_SIZE = 20_000_000
19
import re

datauri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='

imgstr = re.search(r'base64,(.*)', datauri).group(1)

output = open('output.png', 'wb')

output.write(imgstr.decode('base64'))

output.close()
import cStringIO

tempimg = cStringIO.StringIO(imgstr.decode('base64'))

im = Image.open(tempimg)

或者如果你需要把它加载到PIL中:

撰写回答