0

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!

Yonatan
  • 13
  • 4
  • Is it necessary for them to be exactly the same? Depending on the quality and the format the URI may be a little different, but it should still produce a similar picture. – skara9 Nov 28 '21 at 17:15
  • the resize methods are not the same. compare without resizing first – diggusbickus Nov 28 '21 at 17:57
  • @skara9 yes I was able to get a similar image for jpeg, but not for png. I am looking for something that will work exactly like js. – Yonatan Nov 28 '21 at 18:31
  • @diggusbickus This is interesting I will sure try. – Yonatan Nov 28 '21 at 18:32

0 Answers0