mirror of
https://github.com/lovell/sharp.git
synced 2025-07-12 20:10:13 +02:00
Add premultiplied option to composite operation (#1835)
This commit is contained in:
parent
3fa91bb4ce
commit
4ae8999f62
@ -31,6 +31,7 @@ and [https://www.cairographics.org/operators/][2]
|
||||
- `images[].top` **[Number][7]?** the pixel offset from the top edge.
|
||||
- `images[].left` **[Number][7]?** the pixel offset from the left edge.
|
||||
- `images[].tile` **[Boolean][9]** set to true to repeat the overlay image across the entire image with the given `gravity`. (optional, default `false`)
|
||||
- `images[].premultiplied` **[Boolean][9]** set to true to avoid premultipling the image below. Equivalent to the `--premultiplied` vips option. (optional, default `false`)
|
||||
- `images[].density` **[Number][7]** number representing the DPI for vector overlay image. (optional, default `72`)
|
||||
- `images[].raw` **[Object][4]?** describes overlay when using raw pixel data.
|
||||
- `images[].raw.width` **[Number][7]?**
|
||||
|
@ -105,7 +105,8 @@ function composite (images) {
|
||||
tile: false,
|
||||
left: -1,
|
||||
top: -1,
|
||||
gravity: 0
|
||||
gravity: 0,
|
||||
premultiplied: false
|
||||
};
|
||||
if (is.defined(image.blend)) {
|
||||
if (is.string(blend[image.blend])) {
|
||||
@ -147,6 +148,14 @@ function composite (images) {
|
||||
throw is.invalidParameterError('gravity', 'valid gravity', image.gravity);
|
||||
}
|
||||
}
|
||||
if (is.defined(image.premultiplied)) {
|
||||
if (is.bool(image.premultiplied)) {
|
||||
composite.premultiplied = image.premultiplied;
|
||||
} else {
|
||||
throw is.invalidParameterError('premultiplied', 'boolean', image.premultiplied);
|
||||
}
|
||||
}
|
||||
|
||||
return composite;
|
||||
});
|
||||
return this;
|
||||
|
@ -591,7 +591,7 @@ class PipelineWorker : public Nan::AsyncWorker {
|
||||
if (!HasAlpha(compositeImage)) {
|
||||
compositeImage = sharp::EnsureAlpha(compositeImage);
|
||||
}
|
||||
compositeImage = compositeImage.premultiply();
|
||||
if (!composite->premultiplied) compositeImage = compositeImage.premultiply();
|
||||
// Calculate position
|
||||
int left;
|
||||
int top;
|
||||
@ -1230,6 +1230,7 @@ NAN_METHOD(pipeline) {
|
||||
composite->left = AttrTo<int32_t>(compositeObject, "left");
|
||||
composite->top = AttrTo<int32_t>(compositeObject, "top");
|
||||
composite->tile = AttrTo<bool>(compositeObject, "tile");
|
||||
composite->premultiplied = AttrTo<bool>(compositeObject, "premultiplied");
|
||||
baton->composite.push_back(composite);
|
||||
}
|
||||
// Resize options
|
||||
|
@ -41,6 +41,7 @@ struct Composite {
|
||||
int left;
|
||||
int top;
|
||||
bool tile;
|
||||
bool premultiplied;
|
||||
|
||||
Composite():
|
||||
input(nullptr),
|
||||
@ -48,7 +49,8 @@ struct Composite {
|
||||
gravity(0),
|
||||
left(-1),
|
||||
top(-1),
|
||||
tile(false) {}
|
||||
tile(false),
|
||||
premultiplied(false) {}
|
||||
};
|
||||
|
||||
struct PipelineBaton {
|
||||
|
BIN
test/fixtures/expected/expected.absent.composite.premultiplied.png
vendored
Executable file
BIN
test/fixtures/expected/expected.absent.composite.premultiplied.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
test/fixtures/expected/expected.false.composite.premultiplied.png
vendored
Executable file
BIN
test/fixtures/expected/expected.false.composite.premultiplied.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
test/fixtures/expected/expected.true.composite.premultiplied.png
vendored
Executable file
BIN
test/fixtures/expected/expected.true.composite.premultiplied.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
test/fixtures/input.above.composite.premultiplied.png
vendored
Executable file
BIN
test/fixtures/input.above.composite.premultiplied.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
test/fixtures/input.below.composite.premultiplied.png
vendored
Executable file
BIN
test/fixtures/input.below.composite.premultiplied.png
vendored
Executable file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
65
test/unit/composite.js
Normal file → Executable file
65
test/unit/composite.js
Normal file → Executable file
@ -62,6 +62,65 @@ describe('composite', () => {
|
||||
})
|
||||
));
|
||||
|
||||
it('premultiplied true', () => {
|
||||
const filename = 'composite.premultiplied.png';
|
||||
const below = fixtures.path(`input.below.${filename}`);
|
||||
const above = fixtures.path(`input.above.${filename}`);
|
||||
const actual = fixtures.path(`output.true.${filename}`);
|
||||
const expected = fixtures.expected(`expected.true.${filename}`);
|
||||
return sharp(below)
|
||||
.composite([{
|
||||
input: above,
|
||||
blend: 'color-burn',
|
||||
top: 0,
|
||||
left: 0,
|
||||
premultiplied: true
|
||||
}])
|
||||
.toFile(actual)
|
||||
.then(() => {
|
||||
fixtures.assertMaxColourDistance(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
it('premultiplied false', () => {
|
||||
const filename = 'composite.premultiplied.png';
|
||||
const below = fixtures.path(`input.below.${filename}`);
|
||||
const above = fixtures.path(`input.above.${filename}`);
|
||||
const actual = fixtures.path(`output.false.${filename}`);
|
||||
const expected = fixtures.expected(`expected.false.${filename}`);
|
||||
return sharp(below)
|
||||
.composite([{
|
||||
input: above,
|
||||
blend: 'color-burn',
|
||||
top: 0,
|
||||
left: 0,
|
||||
premultiplied: false
|
||||
}])
|
||||
.toFile(actual)
|
||||
.then(() => {
|
||||
fixtures.assertMaxColourDistance(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
it('premultiplied absent', () => {
|
||||
const filename = 'composite.premultiplied.png';
|
||||
const below = fixtures.path(`input.below.${filename}`);
|
||||
const above = fixtures.path(`input.above.${filename}`);
|
||||
const actual = fixtures.path(`output.absent.${filename}`);
|
||||
const expected = fixtures.expected(`expected.absent.${filename}`);
|
||||
return sharp(below)
|
||||
.composite([{
|
||||
input: above,
|
||||
blend: 'color-burn',
|
||||
top: 0,
|
||||
left: 0
|
||||
}])
|
||||
.toFile(actual)
|
||||
.then(() => {
|
||||
fixtures.assertMaxColourDistance(actual, expected);
|
||||
});
|
||||
});
|
||||
|
||||
it('multiple', () => {
|
||||
const filename = 'composite-multiple.png';
|
||||
const actual = fixtures.path(`output.${filename}`);
|
||||
@ -265,6 +324,12 @@ describe('composite', () => {
|
||||
}, /Expected boolean for tile but received invalid of type string/);
|
||||
});
|
||||
|
||||
it('invalid premultiplied', () => {
|
||||
assert.throws(() => {
|
||||
sharp().composite([{ input: 'test', premultiplied: 'invalid' }]);
|
||||
}, /Expected boolean for premultiplied but received invalid of type string/);
|
||||
});
|
||||
|
||||
it('invalid left', () => {
|
||||
assert.throws(() => {
|
||||
sharp().composite([{ input: 'test', left: 0.5 }]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user