Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: retain metadata after image compression #5800

Closed
wants to merge 9 commits into from

Conversation

foochifa
Copy link
Contributor

@foochifa foochifa commented Feb 21, 2023

Problem

In React, the image compression library that we currently use, browser-image-compression, does not retain EXIF metadata of images, as it strips the data before compressing it with html canvas.

As some of our users rely on image metadata, this feature will help retain their workflow even if submission size of images is large. Our previous version in angularjs retains this metadata.

Closes #5754

Solution

Replace the image compression library with compressorjs

Breaking Changes

  • Yes - this PR contains breaking changes
    • Details ...
  • No - this PR is backwards compatible

Features:
EXIF data of JPEG images will now be preserved even after compression.

Before & After Screenshots

BEFORE:

image

AFTER:

image

Tests

  • Go to a form with an attachment field. Attempt to upload a jpeg, with metadata, that has a file size larger than the attachment field. The image should be successfully compressed. Submit the form.
  • Check that the metadata of the original image is preserved in the compressed image, which was submitted to the form.
  • Go to a form with an attachment field. Attempt to upload a png that has a file size larger than the attachment field. The image should be successfully compressed. Submit the form.

New dependencies:

  • compressorjs : javascript lossy and async image compressor using the browser's canvas.toBlob API

@foochifa foochifa requested a review from timotheeg February 21, 2023 06:53
@timotheeg
Copy link
Contributor

Any news from upstream on this one @foochifa ?

@foochifa
Copy link
Contributor Author

foochifa commented Mar 3, 2023

Oh yes @timotheeg ! The package was just released earlier this week, sorry have been busy with the payment issues. Though there is one issue that may arise from this:

Compressorjs does not have a max_size paramter. Hence, even after compression (only for Png files, Jpeg will still work) it may still be quite large. Was testing a png file that compresses from just 2.6MB to 1.1MB even after dropping quality and width/height to 1440 (this is also quite rare, after testing about 8 png files (of size 1-13.1), it only happened for one specific png).

Thats why I have added error checking, to check if:

  • compression fails cause browser doesn't support
  • even after compression, size exceeds the limit

Also the metadata only works for jpeg files currently too haha there isn't any good package to handle metadata for png files (even though exif should have been integrated in 2017)

I have 4 options for this:

  1. When image is still too large after compressing -> compress again at 0.5/0.75 of the previous width (may make compress for some Pngs slower, but it seems like compressorjs is already a bit faster than browser-image-compression)
  2. Keep it as it is, on rare cases (very small, high quality, png files) it might force the user to compress the files themselves
  3. Set a threshold in compressorjs to convert png -> jpeg -> compress -> png again (this will lose features like invisible background, though its unlikely for images with invisible background to be too large after compressing)
  4. Keep browser-image-compression, but extract and append exif data using another package like exifreader

Current implementation is option 3

@foochifa
Copy link
Contributor Author

foochifa commented Mar 6, 2023

Some cool things I have found too:

  1. Theoretically a jpeg exif data can be infinite, so if the exif data is already > maxSize, the compressed image with metadata will always exceed the maxSize.
  2. The largest possible png is width x height x 4B, so around 8MB if we get a square image and resize it to 1440x1440.
  3. Whilst for jpeg is ~width x height x 1B, 2MB if we get a square image.

@foochifa foochifa force-pushed the feat/retain-metadata-from-image-compression branch from fad3315 to c01f333 Compare March 9, 2023 01:27
@foochifa foochifa marked this pull request as ready for review March 9, 2023 03:17
@foochifa
Copy link
Contributor Author

foochifa commented May 12, 2023

CLOSING THIS our current browser-image-compression library, which I think is better as it provides more functionality (having a max_size to iterative compress the file down) just got an update that helps to preserve exif metadata for JPEGs.

Will open a separate PR to bump browser-image-compression and enable the preserve exif flag

@foochifa foochifa closed this May 12, 2023
@timotheeg
Copy link
Contributor

timotheeg commented May 12, 2023

Awesome! Thanks @foochifa !

@KenLSM KenLSM deleted the feat/retain-metadata-from-image-compression branch November 13, 2024 03:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Image metadata stripped after compression
2 participants