mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 18:40:16 +02:00
Add ensureAlpha op, adds alpha channel if missing #1153
This commit is contained in:
parent
8e70579e47
commit
4c01a099ea
@ -16,6 +16,22 @@ sharp('rgba.png')
|
|||||||
|
|
||||||
Returns **Sharp**
|
Returns **Sharp**
|
||||||
|
|
||||||
|
## ensureAlpha
|
||||||
|
|
||||||
|
Ensure alpha channel, if missing. The added alpha channel will be fully opaque. This is a no-op if the image already has an alpha channel.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
sharp('rgb.jpg')
|
||||||
|
.ensureAlpha()
|
||||||
|
.toFile('rgba.png', function(err, info) {
|
||||||
|
// rgba.png is a 4 channel image with a fully opaque alpha channel
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns **Sharp**
|
||||||
|
|
||||||
## extractChannel
|
## extractChannel
|
||||||
|
|
||||||
Extract a single channel from a multi-channel image.
|
Extract a single channel from a multi-channel image.
|
||||||
|
@ -9,6 +9,9 @@ Requires libvips v8.7.0.
|
|||||||
* Ensure shortest edge is at least one pixel after resizing.
|
* Ensure shortest edge is at least one pixel after resizing.
|
||||||
[#1003](https://github.com/lovell/sharp/issues/1003)
|
[#1003](https://github.com/lovell/sharp/issues/1003)
|
||||||
|
|
||||||
|
* Add `ensureAlpha` operation to add an alpha channel, if missing.
|
||||||
|
[#1153](https://github.com/lovell/sharp/issues/1153)
|
||||||
|
|
||||||
* Expose `pages` and `pageHeight` metadata for multi-page input images.
|
* Expose `pages` and `pageHeight` metadata for multi-page input images.
|
||||||
[#1205](https://github.com/lovell/sharp/issues/1205)
|
[#1205](https://github.com/lovell/sharp/issues/1205)
|
||||||
|
|
||||||
|
@ -29,6 +29,23 @@ function removeAlpha () {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure alpha channel, if missing. The added alpha channel will be fully opaque. This is a no-op if the image already has an alpha channel.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* sharp('rgb.jpg')
|
||||||
|
* .ensureAlpha()
|
||||||
|
* .toFile('rgba.png', function(err, info) {
|
||||||
|
* // rgba.png is a 4 channel image with a fully opaque alpha channel
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* @returns {Sharp}
|
||||||
|
*/
|
||||||
|
function ensureAlpha () {
|
||||||
|
this.options.ensureAlpha = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract a single channel from a multi-channel image.
|
* Extract a single channel from a multi-channel image.
|
||||||
*
|
*
|
||||||
@ -120,6 +137,7 @@ module.exports = function (Sharp) {
|
|||||||
Object.assign(Sharp.prototype, {
|
Object.assign(Sharp.prototype, {
|
||||||
// Public instance functions
|
// Public instance functions
|
||||||
removeAlpha,
|
removeAlpha,
|
||||||
|
ensureAlpha,
|
||||||
extractChannel,
|
extractChannel,
|
||||||
joinChannel,
|
joinChannel,
|
||||||
bandbool
|
bandbool
|
||||||
|
@ -144,6 +144,7 @@ const Sharp = function (input, options) {
|
|||||||
joinChannelIn: [],
|
joinChannelIn: [],
|
||||||
extractChannel: -1,
|
extractChannel: -1,
|
||||||
removeAlpha: false,
|
removeAlpha: false,
|
||||||
|
ensureAlpha: false,
|
||||||
colourspace: 'srgb',
|
colourspace: 'srgb',
|
||||||
// overlay
|
// overlay
|
||||||
overlayGravity: 0,
|
overlayGravity: 0,
|
||||||
|
@ -38,6 +38,18 @@ namespace sharp {
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ensures alpha channel, if missing.
|
||||||
|
*/
|
||||||
|
VImage EnsureAlpha(VImage image) {
|
||||||
|
if (!HasAlpha(image)) {
|
||||||
|
std::vector<double> alpha;
|
||||||
|
alpha.push_back(sharp::MaximumImageAlpha(image.interpretation()));
|
||||||
|
image = image.bandjoin_const(alpha);
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Composite overlayImage over image at given position
|
Composite overlayImage over image at given position
|
||||||
Assumes alpha channels are already premultiplied and will be unpremultiplied after
|
Assumes alpha channels are already premultiplied and will be unpremultiplied after
|
||||||
|
@ -30,6 +30,11 @@ namespace sharp {
|
|||||||
*/
|
*/
|
||||||
VImage RemoveAlpha(VImage image);
|
VImage RemoveAlpha(VImage image);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ensures alpha channel, if missing.
|
||||||
|
*/
|
||||||
|
VImage EnsureAlpha(VImage image);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Alpha composite src over dst with given gravity.
|
Alpha composite src over dst with given gravity.
|
||||||
Assumes alpha channels are already premultiplied and will be unpremultiplied after.
|
Assumes alpha channels are already premultiplied and will be unpremultiplied after.
|
||||||
|
@ -677,6 +677,11 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|||||||
image = sharp::RemoveAlpha(image);
|
image = sharp::RemoveAlpha(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure alpha channel, if missing
|
||||||
|
if (baton->ensureAlpha) {
|
||||||
|
image = sharp::EnsureAlpha(image);
|
||||||
|
}
|
||||||
|
|
||||||
// Convert image to sRGB, if not already
|
// Convert image to sRGB, if not already
|
||||||
if (sharp::Is16Bit(image.interpretation())) {
|
if (sharp::Is16Bit(image.interpretation())) {
|
||||||
image = image.cast(VIPS_FORMAT_USHORT);
|
image = image.cast(VIPS_FORMAT_USHORT);
|
||||||
@ -1236,6 +1241,7 @@ NAN_METHOD(pipeline) {
|
|||||||
baton->extractChannel = AttrTo<int32_t>(options, "extractChannel");
|
baton->extractChannel = AttrTo<int32_t>(options, "extractChannel");
|
||||||
|
|
||||||
baton->removeAlpha = AttrTo<bool>(options, "removeAlpha");
|
baton->removeAlpha = AttrTo<bool>(options, "removeAlpha");
|
||||||
|
baton->ensureAlpha = AttrTo<bool>(options, "ensureAlpha");
|
||||||
if (HasAttr(options, "boolean")) {
|
if (HasAttr(options, "boolean")) {
|
||||||
baton->boolean = CreateInputDescriptor(AttrAs<v8::Object>(options, "boolean"), buffersToPersist);
|
baton->boolean = CreateInputDescriptor(AttrAs<v8::Object>(options, "boolean"), buffersToPersist);
|
||||||
baton->booleanOp = sharp::GetBooleanOperation(AttrAsStr(options, "booleanOp"));
|
baton->booleanOp = sharp::GetBooleanOperation(AttrAsStr(options, "booleanOp"));
|
||||||
|
@ -142,6 +142,7 @@ struct PipelineBaton {
|
|||||||
VipsOperationBoolean bandBoolOp;
|
VipsOperationBoolean bandBoolOp;
|
||||||
int extractChannel;
|
int extractChannel;
|
||||||
bool removeAlpha;
|
bool removeAlpha;
|
||||||
|
bool ensureAlpha;
|
||||||
VipsInterpretation colourspace;
|
VipsInterpretation colourspace;
|
||||||
int tileSize;
|
int tileSize;
|
||||||
int tileOverlap;
|
int tileOverlap;
|
||||||
@ -237,6 +238,7 @@ struct PipelineBaton {
|
|||||||
bandBoolOp(VIPS_OPERATION_BOOLEAN_LAST),
|
bandBoolOp(VIPS_OPERATION_BOOLEAN_LAST),
|
||||||
extractChannel(-1),
|
extractChannel(-1),
|
||||||
removeAlpha(false),
|
removeAlpha(false),
|
||||||
|
ensureAlpha(false),
|
||||||
colourspace(VIPS_INTERPRETATION_LAST),
|
colourspace(VIPS_INTERPRETATION_LAST),
|
||||||
tileSize(256),
|
tileSize(256),
|
||||||
tileOverlap(0),
|
tileOverlap(0),
|
||||||
|
@ -115,6 +115,7 @@ describe('Alpha transparency', function () {
|
|||||||
fixtures.inputWebP
|
fixtures.inputWebP
|
||||||
].map(function (input) {
|
].map(function (input) {
|
||||||
return sharp(input)
|
return sharp(input)
|
||||||
|
.resize(10)
|
||||||
.removeAlpha()
|
.removeAlpha()
|
||||||
.toBuffer({ resolveWithObject: true })
|
.toBuffer({ resolveWithObject: true })
|
||||||
.then(function (result) {
|
.then(function (result) {
|
||||||
@ -122,4 +123,24 @@ describe('Alpha transparency', function () {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Ensures alpha from fixtures without transparency, ignores those with', function () {
|
||||||
|
return Promise.all([
|
||||||
|
fixtures.inputPngWithTransparency,
|
||||||
|
fixtures.inputPngWithTransparency16bit,
|
||||||
|
fixtures.inputWebPWithTransparency,
|
||||||
|
fixtures.inputJpg,
|
||||||
|
fixtures.inputPng,
|
||||||
|
fixtures.inputWebP
|
||||||
|
].map(function (input) {
|
||||||
|
return sharp(input)
|
||||||
|
.resize(10)
|
||||||
|
.ensureAlpha()
|
||||||
|
.png()
|
||||||
|
.toBuffer({ resolveWithObject: true })
|
||||||
|
.then(function (result) {
|
||||||
|
assert.strictEqual(4, result.info.channels);
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user