-1

I have img from other server

<img src="https://cloudserver/1.jpg">

On click this img i want convert to File object for send post request to server. After this function i see that data all bytes = 0, dont understand what happing ? In search i find problem about that need wait then image is loading done but i 100% have already loaded image.

imgToFile: function (imageElement){
    imageElement.crossOrigin="anonymous";

    var canvasElement = document.createElement("canvas");
    canvasElement.width = imageElement.width;
    canvasElement.height = imageElement.height;
    var canvasContext = canvasElement.getContext("2d");
    canvasContext.drawImage(imageElement, 0, 0);

    var imageData = canvasContext.getImageData(0, 0, imageElement.width, imageElement.height).data;
    var buffer = new Uint8Array(imageData.length);
    for(var index = 0; index < imageData.length; index++)
        buffer[index] = imageData[index];

    var imageBlob = new Blob(buffer);
    return new File([imageBlob], /\/([^/]+)$/.exec(imageElement.src)[1]);
}

Sandbox: https://liveweave.com/DCXuNY

padavan
  • 714
  • 8
  • 22
  • Please share a working example showing how all methods are being called. Quite weird you have zeroes though, you should only have an error because setting `crossOrigin` won't make the image refetch the resource, meaning that you should be tainting your canvas by drawing this image, and that you should never reach anything after `getImageData`. – Kaiido May 31 '20 at 07:28
  • hi, i added sandbox – padavan May 31 '20 at 08:25

1 Answers1

1

That's quite surprising to me who thought I knew this part of the specs, but turns out that since 2016, changing the crossorigin attribute state is part of the img's relevant mutations, which will force a refetching of the image source.

Chrome only caught up with the specs relatively recently (M84), Firefox still hasn't and will thus just throw an Error complaining about the fact the image did taint the canvas.

Chrome on the other hand will thus refetch the image as soon as you change that crossOrigin IDL attribute, this time with the proper CORS headers. So at the time you hit drawImage in that browser, it still won't have fetched the CORS compliant resource (even though it's the same file, because it's served with different headers, browsers will fetch it entirely again).

So contrarily to what you thought, your image is still not loaded in Chrome.

To fix that, you could add an onload event handler in your js script, but you'd also need to force the refetching of the image for other browsers by setting again the src attribute (even to the same value):

onload = (evt) => {
  const img = document.querySelector( 'img' );
  img.onload = (evt) => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    ctx.drawImage(img,0,0);
    console.log(...ctx.getImageData(250,120,1,1).data);
  };
  img.crossOrigin = 'anonymous';
  img.src = img.src; // force refetching for non-Chrome browsers
};
img { width: 300px }
<img src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png">

But the best is certainly to request your image directly with the proper CORS headers, from the beginning, so you don't make your users download two times the same file for nothing.

onload = (evt) => {
  const img = document.querySelector( 'img' );
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  ctx.drawImage(img,0,0);
  console.log(...ctx.getImageData(250,120,1,1).data);
};
img { width: 300px }
<img src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png" crossorigin="anonymous">
Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • wow! its very hardcore knowledge :) I try use second variant and now all work without double download. Thx! P.S. Intresting why in Question variant i didnt watch second downloading in chrome network tab ? – padavan May 31 '20 at 12:27
  • about P.S. last comment i I figured it out :) – padavan May 31 '20 at 12:35