On an application where the client side is implemented in javascript I receive input images and send them back to the server using the following scheme:
allImagesToSend = [];
for (var i = 0; i < files.length; ++i) {
var file = files.item(i);
if (file.type == "image/jpeg" || file.type == "image/png") {
var reader = new FileReader();
reader.onload = function(readerEvent) {
var image = new Image();
image.onload = function(imageEvent) {
h = 224
w = 224
var canvas = document.createElement('canvas');
canvas.width = w;
canvas.height = h;
canvas.getContext('2d').drawImage(image, 0, 0, w, h);
if (file.type == "image/jpeg") {
var dataURL = canvas.toDataURL("image/jpeg", 1.0);
} else {
var dataURL = canvas.toDataURL("image/png");
}
allImagesToSend.push(dataURL); // <--- adding here all the images encodings.
}
image.src = readerEvent.target.result;
}
reader.readAsDataURL(file);
}
...
and then I send the stringified instance of the list of images:
JSON.stringify(allImagesToSend)
On the server which is written in python, I do:
def parse_images(data):
images_encoded = data['images'].split(',')[1::2]
images_bytes = [base64.decodebytes(image_encoded.encode('utf-8')) for image_encoded in images_encoded]
images = [np.array(Image.open(io.BytesIO(image_bytes))) for image_bytes in images_bytes]
return images
where data['images']
looks (as expected) like this:
'data:image/png;base64,iVBORw0KGgoAAAANSUhE...,data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAO....
I would like to simulate this behavior from python. For reference I was reading: here and here and here.
After many tries I ended up with:
def to_data_url(images):
"""
Convert local PNG's/JPEG's similar to javascripts canvas.toDataUrl.
Args:
images: a list of .png or .jpeg files.
"""
w, h = 224, 224
# convert to PIL Images.
images_pil = [Image.open(img).resize((w, h)) for img in images]
uris = []
for url, im in zip(images, images_pil):
encoded_string = ""
ext = 'png' if isinstance(url, str) and url.endswith('png') else 'jpeg'
sep = f"data:image/{ext};base64,"
output = io.BytesIO()
im.save(output, ext.upper(), quality=100 if ext == 'jpeg' else None,
subsampling=0 if ext == 'jpeg' else None)
encoded_string += sep
encoded_string += base64.b64encode(output.getvalue()).decode("utf-8")
uris.append(encoded_string)
return ",".join(uris)
But using diff on the output of canvas.toDataUrl and my python function I see clearly that the two are not the same. Any ideas? Thanks!