Skip to content

Commit

Permalink
accept premultiplied raw inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
mnutt committed Apr 29, 2021
1 parent f8a7637 commit 3047585
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
inputDescriptor.rawWidth = inputOptions.raw.width;
inputDescriptor.rawHeight = inputOptions.raw.height;
inputDescriptor.rawChannels = inputOptions.raw.channels;
if (is.bool(inputOptions.raw.premultiplied)) {
inputDescriptor.rawPremultiplied = inputOptions.raw.premultiplied;
}
} else {
throw new Error('Expected width, height and channels for raw pixel input');
}
Expand Down
7 changes: 7 additions & 0 deletions src/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ namespace sharp {
descriptor->rawWidth = AttrAsUint32(input, "rawWidth");
descriptor->rawHeight = AttrAsUint32(input, "rawHeight");
}
// Raw pixel input is premultiplied
if (HasAttr(input, "rawPremultiplied")) {
descriptor->rawPremultiplied = AttrAsBool(input, "rawPremultiplied");
}
// Multi-page input (GIF, TIFF, PDF)
if (HasAttr(input, "pages")) {
descriptor->pages = AttrAsInt32(input, "pages");
Expand Down Expand Up @@ -301,6 +305,9 @@ namespace sharp {
} else {
image.get_image()->Type = VIPS_INTERPRETATION_sRGB;
}
if (descriptor->rawPremultiplied) {
image = image.unpremultiply();
}
imageType = ImageType::RAW;
} else {
// Compressed data
Expand Down
2 changes: 2 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ namespace sharp {
int rawChannels;
int rawWidth;
int rawHeight;
bool rawPremultiplied;
int pages;
int page;
int level;
Expand All @@ -80,6 +81,7 @@ namespace sharp {
rawChannels(0),
rawWidth(0),
rawHeight(0),
rawPremultiplied(false),
pages(1),
page(0),
level(0),
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ module.exports = {
inputPngEmbed: getPath('embedgravitybird.png'), // Released to sharp under a CC BY 4.0
inputPngRGBWithAlpha: getPath('2569067123_aca715a2ee_o.png'), // http://www.flickr.com/photos/grizdave/2569067123/ (same as inputJpg)
inputPngImageInAlpha: getPath('image-in-alpha.png'), // https://github.com/lovell/sharp/issues/1597
inputPngSolidAlpha: getPath('with-alpha.png'), // https://github.com/lovell/sharp/issues/1599

inputWebP: getPath('4.webp'), // http://www.gstatic.com/webp/gallery/4.webp
inputWebPWithTransparency: getPath('5_webp_a.webp'), // http://www.gstatic.com/webp/gallery3/5_webp_a.webp
Expand Down
Binary file added test/fixtures/with-alpha.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions test/unit/raw.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,53 @@ describe('Raw pixel data', function () {
});
});

it('RGBA premultiplied', function (done) {
// Convert to raw pixel data
sharp(fixtures.inputPngSolidAlpha)
.resize(256)
.raw()
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(256, info.width);
assert.strictEqual(192, info.height);
assert.strictEqual(4, info.channels);

const originalData = Buffer.from(data);

// Premultiply image data
for (let i = 0; i < data.length; i += 4) {
const alpha = data[i + 3];
const norm = alpha / 255;

if (alpha < 255) {
data[i] = Math.round(data[i] * norm);
data[i + 1] = Math.round(data[i + 1] * norm);
data[i + 2] = Math.round(data[i + 2] * norm);
}
}
const d = data;

// Convert back to PNG
sharp(data, {
raw: {
width: info.width,
height: info.height,
channels: info.channels,
premultiplied: true
}
})
.raw()
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(256, info.width);
assert.strictEqual(192, info.height);
assert.strictEqual(4, info.channels);
assert.equal(data.compare(originalData), 0, 'output buffer matches unpremultiplied input buffer');
done();
});
});
});

it('JPEG to raw Stream and back again', function (done) {
const width = 32;
const height = 24;
Expand Down

0 comments on commit 3047585

Please sign in to comment.