pica: Images (randomly?) corrupted with Firefox 58+
Hi,
I have been trying to debug this for some time and I would like to get your insight on this.
On my app, users can upload a lot of pictures, and I am using pica to resize them before uploading. On Firefox (saw this happening for users on mac, linux and windows) some images, not always the same when I try multiple times, are not correct once on the server. As I am calculating the checksum before upload, it is not caused by a network error.
Here is an example:
- Original image: https://www.dropbox.com/s/go5tra5czulbfsm/IMGL7717.jpg?dl=0
- Image after processing: https://www.dropbox.com/s/37n7ba5qhcl8vfq/314luvAL9s5OcI0ugieEKK-3cf7b61d9e.jpg?dl=0
I am using a code inspired by https://github.com/nodeca/nodeca.users/blob/master/client/users/uploader/uploader.js to extract the EXIF data, resize the image using pica
, and then put it back together.
For each file:
- Read it using
readAsArrayBuffer
- call
filterJPEG
- create a new
Image
- set the
src
usingwindow.URL.createObjectURL(file)
- create 2
canvas
elements, set their size - draw the image on the first one
- call pica to resize on the second canvas (one shared pica instance, using
const pica = Pica({ idle: 10000 })
) - get a blob from the
dst
canvas - put back together the JPEG header (from
filterJPEG
) and the body from the blob
Once this is done, I use a webworker to calculate the MD5 checksum of the previously created blob
, and upload it to my server (where the MD5 checksum is checked again).
Do you have an idea of what can cause this? There are a lot of moving parts and I am only seeing the issue on Firefox. I would estimate than less than 0.5% of the files are corrupted like this, and retrying a corrupted file usually works fine. I havent seen this problem on Safari / Chrome.
I know this may not be related to Pica, but I spent quite a lot of time trying to understand where it may come from, and I am not sure of how to pin it down.
Thanks!
UPD: probably a browser bug https://github.com/nodeca/pica/issues/130#issuecomment-371617724
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 18 (8 by maintainers)
FYI the bug has been fixed (see the bugzilla link above). I am no longer able to reproduce it using Firefox Beta (v61). The fix may be backported to Firefox 60 ESR if it does not cause any regression.
Firefox 61 is planned to be released on 2018-06-26.
Here is the bugzilla link: https://bugzilla.mozilla.org/show_bug.cgi?id=1450302
I havent forgotten this bug, here are some updates.
I discussed this with a Firefox developer and confirmed this is a Firefox bug. After some tests it does not comes from
canvas
but from the file loading (from both drag & drop or<input type="file">
). We made this simple test case: https://github.com/renchap/testcase-canvas-image/blob/master/index-simple.htmlWhen selecting big images (we reproduced it with 20 2+ MB JPEG files, but you get better repro chances if you have more images), the code generates an object URL for each and displays it. Some of them, randomly, are corrupted (bottom of the image is white).
I used https://mozilla.github.io/mozregression/ to find out when it has been introduced (similar to git bisect, but using pre-build Firefox binaries). It looks like this bug has been introduced in https://hg.mozilla.org/integration/mozilla-inbound/rev/075e7eef53f4 The first public release with this commit was Firefox 58 (released on 23 Jan 2018), which is consistent with the user reports we got.
We will soon open a bug with Firefox, and I will post the URL here.
This is definitely a FF bug with Canvas. In another app I am using https://github.com/blueimp/JavaScript-Load-Image to resize images using Canvas and store thumbnails as data URLs, and I sometimes see corrupted images (like the one I posted above, bottom part of the image is white, sometimes its 80% of the image, sometimes more, sometimes less). I will open a Firefox bug once I have a way to reproduce it, and will link it here. I plan to write a simple File => dataurl function and call it in a loop until it generated a corrupted image. I am trying to figure out how to detect that an image is corrupted, so I can automate the whole process.