premultiplied Usage: When compress png with premulitiplied, then output png shows bad.
Possible bug
// Copyright 2013 Lovell Fuller and others.
// SPDX-License-Identifier: Apache-2.0
'use strict';
const sharp = require('sharp');
sharp('PariteShip.png',{ premultiplied: true })
.png({ quality: 80},{ premultiplied: true })
.toFile('compressed.png',{ premultiplied: true })
What is the expected behaviour?
If I delete the compress code, then output png shows good.
below is the correct result
Is this LLM-generated code? None of these functions accept premultiplied as an option.
When you provide a quality option to png() you are selecting to use lossy, quantised, palette-based output.
https://sharp.pixelplumbing.com/api-output/#png
Is this LLM-generated code? None of these functions accept
premultipliedas an option.When you provide a
qualityoption topng()you are selecting to use lossy, quantised, palette-based output.https://sharp.pixelplumbing.com/api-output/#png
I wrote it , just for test the premultiplied usage. Is that possible to compress the png to support premultiplied ? Instead I use the tinypng to compress the png, the output png shows good.
I think the best thing for you to do is create a complete, minimal, standalone repo with code and image(s) that allows someone else to reproduce and therefore understand what you're looking for.
@tangkaikk Were you able to make any progress with this? If you still require help, please can you provide the requested info.
pic-compressShowBad.zip Here is the minimal repo for you. There are two pics under folder pic-compressShowBad\assets\main\native\4a, the one named "4a28a44c-8feb-4ca5-9913-9dd8d2b023c7" shows bad which compressed by sharp, the other one "PariteShip-goodPic" shows good which is the original picture.
The compress code is below:
const sharp = require('sharp');
sharp('PariteShip.png')
.png({ quality: 80})
.toFile('compressed.png')
Thanks, as I mentioned above, when you provide a quality option to png() you are selecting to use lossy, quantised, palette-based output.
https://sharp.pixelplumbing.com/api-output/#png
The sample image provided is already a palette-based image that has the maximum 256 palette entries (768 bytes is 256 RGB entries):
$ pngchunks PariteShip-goodPic.png | grep PLTE
Chunk: Data Length 768 (max 2147483647), Type 1163152464 [PLTE]
By selecting a quality of 80 you are reducing the palette size (474 bytes is 158 RGB entries):
$ pngchunks 4a28a44c-8feb-4ca5-9913-9dd8d2b023c7.png | grep PLTE
Chunk: Data Length 474 (max 2147483647), Type 1163152464 [PLTE]
I would suggest you use palette: true and do not provide a quality:
- .png({ quality: 80 })
+ .png({ palette: true })
Use the suggestion, the problem still exist.
This looks like an artefact of the quantisation process used to reduce the number of colours in an image, hence my original comment about palette size.
You might have some luck removing the use of dithering by setting dither to zero.
.png({ palette: true, dither: 0 })
If this doesn't produce suitable output, I'd probably avoid palette-based PNG entirely given quality appears to be of your greatest concern.
The output still the same. The original picture has been premultiplied Alpha, how can I keep it? Of course, when I remove premultiplied Alpha, the output turns right. My greatest concern is use the sharp to shrink the picture size meanwhile it can still keep the premultiplied Alpha result.
I set the premultiplied option true, but output info it turns false.
The premultiplied input property you've highlighted is for raw pixel based input, which you do not appear to be using.
The premultiplied output property you've highlighted tells you whether any operations in the pipeline resulted in sharp applying a premultiply/unpremultiply roundtrip whilst processing, as documented by toFile:
infocontains the output imageformat,size(bytes),width,height,channelsandpremultiplied(indicating if premultiplication was used).
As I mentioned above, I think the best thing for you to do is create a complete, minimal, standalone repo with code and image(s) that allows someone else to reproduce and therefore understand what you're looking for.
As I mention before, the original pic is premultiplied one. I use raw.premultiplied option to avoid sharp premultiplying the image, but the output file which I copy to the folder pic-compressShowBad\assets\main\native\4a and renamed is as "4a28a44c-8feb-4ca5-9913-9dd8d2b023c7" shows bad.
Here is the code I use:
const sharp = require('sharp');
async function checkAndCompressPng(inputPath, outputPath) {
try {
// Load image and check metadata
let options = new Object();
options["raw"]= new Object();
options["raw"]["premultiplied"] = true;
options["raw"]["width"] = 2048;
options["raw"]["height"] = 1024;
options["raw"]["channels"] = 4;
const image = sharp(inputPath, options);
// Compress PNG
await image
.png({
progressive: true,
palette: true,
quality: 60
})
.keepMetadata()
.toFile(outputPath,(err,info)=>{
console.log("info",info);
});
} catch (err) {
console.error("Error:", err);
}
}
checkAndCompressPng('PariteShip.png', 'output.png');