Загрузите холст html5 в изображение PIL с Django
Я пытаюсь получить содержимое холста 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')
И вот где я застрял. Я не могу понять, как получить URL-адрес данных с кодировкой base64, чтобы загрузить изображение в полезную форму с помощью PIL.
Спасибо!
edit: вот код для нижнего комментария:
>>> d
'data:image/png;base64,iVBORw0K'
>>> d.strip('data:image/png;base64,')
'VBORw0K'
Ответы
Ответ 1
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()
или если вам нужно загрузить его в PIL:
import cStringIO
tempimg = cStringIO.StringIO(imgstr.decode('base64'))
im = Image.open(tempimg)
Ответ 2
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
# 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 МБ):
# canvas data urls are large
DATA_UPLOAD_MAX_MEMORY_SIZE = 20_000_000
Ответ 3
В 2019 году с python3 я попытался ответить 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()