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

Saving anything as PNG produces massive files #77

Closed
miloxeon opened this issue Sep 28, 2024 · 3 comments
Closed

Saving anything as PNG produces massive files #77

miloxeon opened this issue Sep 28, 2024 · 3 comments
Labels
question Further information is requested

Comments

@miloxeon
Copy link

Hi again!

When I convert a 3.8 MB JPEG image to PNG, the result is 12.4 MB. It doesn't depend on Q value: the size is the same for both Q = 100 and Q = 30. Here's my worker code:

import Vips from './vendor/vips-es6.js'
const vips = await Vips()

onmessage = async ({ data: { file } }) => {
	const image = vips.Image.newFromBuffer(await file.arrayBuffer()) // file is an image from input[type="file"]
	const params = { Q: 30 } // changing Q to 100 has no effect
	const blob = new Blob([image.writeToBuffer('.png', params)], { type: 'image/png' })
	image.delete()
	const url = URL.createObjectURL(blob)
	postMessage({ ok: true, url, name: file.name })
}

I feel like I'm missing something very simple. Plus, wasm-vips supposedly includes libimagequant that is well-known for producing small PNG files.

How do I enable high-quality lossy compression?

@miloxeon
Copy link
Author

miloxeon commented Sep 28, 2024

Here are my files, before and after: large-pngs.zip

@kleisauke kleisauke added the question Further information is requested label Sep 28, 2024
@kleisauke
Copy link
Owner

You'll need to set pallete to true if you want to save to a palette-based (i.e. lossy) PNG.

@@ -3,7 +3,7 @@ const vips = await Vips()
 
 onmessage = async ({ data: { file } }) => {
   const image = vips.Image.newFromBuffer(await file.arrayBuffer()) // file is an image from input[type="file"]
-  const params = { Q: 30 } // changing Q to 100 has no effect
+  const params = { Q: 30, palette: true }
   const blob = new Blob([image.writeToBuffer('.png', params)], { type: 'image/png' })
   image.delete()
   const url = URL.createObjectURL(blob)

wasm-vips/lib/vips.d.ts

Lines 8715 to 8718 in 4702f7d

/**
* Quantise to 8bpp palette.
*/
palette?: boolean

See also: https://www.libvips.org/API/current/VipsForeignSave.html#vips-pngsave.

Note that sharp automagically set this to true when you use .png({ quality: 30 }).
https://github.com/lovell/sharp/blob/v0.33.5/lib/output.js#L573-L577

@miloxeon
Copy link
Author

Yes, that seems to do the trick. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants