mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 18:40:16 +02:00
Ensure image is unpremultiplied before composite #3334
This commit is contained in:
parent
a44168c8c7
commit
a618ce7a15
@ -52,6 +52,9 @@ Requires libvips v8.13.0
|
|||||||
Emit warnings when previous calls in the same pipeline will be ignored.
|
Emit warnings when previous calls in the same pipeline will be ignored.
|
||||||
[#3319](https://github.com/lovell/sharp/issues/3319)
|
[#3319](https://github.com/lovell/sharp/issues/3319)
|
||||||
|
|
||||||
|
* Ensure resized image is unpremultiplied before composite.
|
||||||
|
[#3334](https://github.com/lovell/sharp/issues/3334)
|
||||||
|
|
||||||
## v0.30 - *dresser*
|
## v0.30 - *dresser*
|
||||||
|
|
||||||
Requires libvips v8.12.2
|
Requires libvips v8.12.2
|
||||||
|
@ -590,6 +590,18 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
baton->sharpenX1, baton->sharpenY2, baton->sharpenY3);
|
baton->sharpenX1, baton->sharpenY2, baton->sharpenY3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reverse premultiplication after all transformations
|
||||||
|
if (shouldPremultiplyAlpha) {
|
||||||
|
image = image.unpremultiply();
|
||||||
|
// Cast pixel values to integer
|
||||||
|
if (sharp::Is16Bit(image.interpretation())) {
|
||||||
|
image = image.cast(VIPS_FORMAT_USHORT);
|
||||||
|
} else {
|
||||||
|
image = image.cast(VIPS_FORMAT_UCHAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
baton->premultiplied = shouldPremultiplyAlpha;
|
||||||
|
|
||||||
// Composite
|
// Composite
|
||||||
if (shouldComposite) {
|
if (shouldComposite) {
|
||||||
std::vector<VImage> images = { image };
|
std::vector<VImage> images = { image };
|
||||||
@ -670,18 +682,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
image = VImage::composite(images, modes, VImage::option()->set("x", xs)->set("y", ys));
|
image = VImage::composite(images, modes, VImage::option()->set("x", xs)->set("y", ys));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse premultiplication after all transformations:
|
|
||||||
if (shouldPremultiplyAlpha) {
|
|
||||||
image = image.unpremultiply();
|
|
||||||
// Cast pixel values to integer
|
|
||||||
if (sharp::Is16Bit(image.interpretation())) {
|
|
||||||
image = image.cast(VIPS_FORMAT_USHORT);
|
|
||||||
} else {
|
|
||||||
image = image.cast(VIPS_FORMAT_UCHAR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
baton->premultiplied = shouldPremultiplyAlpha;
|
|
||||||
|
|
||||||
// Gamma decoding (brighten)
|
// Gamma decoding (brighten)
|
||||||
if (baton->gammaOut >= 1 && baton->gammaOut <= 3) {
|
if (baton->gammaOut >= 1 && baton->gammaOut <= 3) {
|
||||||
image = sharp::Gamma(image, baton->gammaOut);
|
image = sharp::Gamma(image, baton->gammaOut);
|
||||||
|
@ -447,4 +447,26 @@ describe('composite', () => {
|
|||||||
assert.strictEqual(info.width, 40);
|
assert.strictEqual(info.width, 40);
|
||||||
assert.strictEqual(info.height, 40);
|
assert.strictEqual(info.height, 40);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Ensure implict unpremultiply after resize but before composite', async () => {
|
||||||
|
const [r, g, b, a] = await sharp({
|
||||||
|
create: {
|
||||||
|
width: 1, height: 1, channels: 4, background: 'saddlebrown'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.resize({ width: 8 })
|
||||||
|
.composite([{
|
||||||
|
input: Buffer.from([255, 255, 255, 128]),
|
||||||
|
raw: { width: 1, height: 1, channels: 4 },
|
||||||
|
tile: true,
|
||||||
|
blend: 'dest-in'
|
||||||
|
}])
|
||||||
|
.raw()
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
assert.strictEqual(r, 139);
|
||||||
|
assert.strictEqual(g, 69);
|
||||||
|
assert.strictEqual(b, 19);
|
||||||
|
assert.strictEqual(a, 128);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user