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

PNG compression loses quality in some cases #172

Closed
ysabri opened this issue Dec 19, 2022 · 3 comments
Closed

PNG compression loses quality in some cases #172

ysabri opened this issue Dec 19, 2022 · 3 comments

Comments

@ysabri
Copy link

ysabri commented Dec 19, 2022

I haven't been able to determine what exactly about some PNGs that cause the compression algorithm that results in a visible reduction in quality.

The image I was able to reproduce this with is a PNG image that is 451KB big. When it gets compressed (using the code below) it becomes 169KB. If I just change the extension of the file to JPEG, the converted image is 355KB.

Here are the config params:

imageCompression(file, { alwaysKeepResolution: true, maxIteration: 150, maxSizeMB: 0.4, maxWidthOrHeight: 1440, })

Here is the PNG image before:

Prince_TristanV2

Here is the PNG image after:

Prince_TristanV2-min

Here is the JPEG image after:

PrinceTristanV2Copy-min

Would be the reasoning behind this and is there something I'm missing that I could do to avoid this?

@ysabri
Copy link
Author

ysabri commented Jan 4, 2023

I found a hack that works for those who are facing this issue:

  const IMG_JPEG_TYPE = "image/jpeg";
  const IMG_PNG_TYPE = "image/png";

  let imgWasPng = false;
  if (file.type === IMG_PNG_TYPE) {
    imgWasPng = true;
    const blob = new Blob([file], {type: IMG_JPEG_TYPE});
    file = new File([blob], file.name, {type: IMG_JPEG_TYPE});
  }

  return imageCompression(file, {
    alwaysKeepResolution: true,
    maxIteration: 150,
    maxSizeMB: 0.4,
    maxWidthOrHeight: 1440,
  }).then((compressedFile) => {
    if (imgWasPng) {
      const blob = new Blob([compressedFile], {type: IMG_PNG_TYPE});
      return new File([blob], compressedFile.name, {type: IMG_PNG_TYPE});
    }
    return compressedFile;
  });

@Donaldcwl
Copy link
Owner

When looking at your sample images, it is hard to notice that there are quality differences.

The algorithm handling jpg and png is different because png can have a transparent background.

@Donaldcwl
Copy link
Owner

I found a hack that works for those who are facing this issue:

  const IMG_JPEG_TYPE = "image/jpeg";
  const IMG_PNG_TYPE = "image/png";

  let imgWasPng = false;
  if (file.type === IMG_PNG_TYPE) {
    imgWasPng = true;
    const blob = new Blob([file], {type: IMG_JPEG_TYPE});
    file = new File([blob], file.name, {type: IMG_JPEG_TYPE});
  }

  return imageCompression(file, {
    alwaysKeepResolution: true,
    maxIteration: 150,
    maxSizeMB: 0.4,
    maxWidthOrHeight: 1440,
  }).then((compressedFile) => {
    if (imgWasPng) {
      const blob = new Blob([compressedFile], {type: IMG_PNG_TYPE});
      return new File([blob], compressedFile.name, {type: IMG_PNG_TYPE});
    }
    return compressedFile;
  });

If you do not care about transparent background of png and wanted to treat it as jpg during compression, you can use the options.fileType instead.

For example:
{ alwaysKeepResolution: true, maxIteration: 150, maxSizeMB: 0.4, maxWidthOrHeight: 1440, fileType: 'image/jpeg' }

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

No branches or pull requests

2 participants