mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 18:40:16 +02:00
Add unflatten operation to create an alpha channel (#3461)
This commit is contained in:
parent
b9c3851515
commit
a4c6eba7d4
@ -217,6 +217,7 @@ const Sharp = function (input, options) {
|
||||
tintB: 128,
|
||||
flatten: false,
|
||||
flattenBackground: [0, 0, 0],
|
||||
unflatten: false,
|
||||
negate: false,
|
||||
negateAlpha: true,
|
||||
medianSize: 0,
|
||||
|
7
lib/index.d.ts
vendored
7
lib/index.d.ts
vendored
@ -427,6 +427,13 @@ declare namespace sharp {
|
||||
*/
|
||||
flatten(flatten?: boolean | FlattenOptions): Sharp;
|
||||
|
||||
/**
|
||||
* Unflatten - add an alpha channel to the image if required, and make white pixels fully transparent. Alpha for non-white pixels will be unchanged/opaque.
|
||||
* @param unflatten true to enable and false to disable (defaults to true)
|
||||
* @returns A sharp instance that can be used to chain operations
|
||||
*/
|
||||
unflatten(unflatten?: boolean): Sharp;
|
||||
|
||||
/**
|
||||
* Apply a gamma correction by reducing the encoding (darken) pre-resize at a factor of 1/gamma then increasing the encoding (brighten) post-resize at a factor of gamma.
|
||||
* This can improve the perceived brightness of a resized image in non-linear colour spaces.
|
||||
|
@ -405,6 +405,25 @@ function flatten (options) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unflatten - add an alpha channel to the image if required, and make white pixels fully transparent. Alpha for non-white pixels will be unchanged/opaque.
|
||||
*
|
||||
* @example
|
||||
* await sharp(rgbInput)
|
||||
* .unflatten()
|
||||
* .toBuffer();
|
||||
*
|
||||
* @example
|
||||
* await sharp(rgbInput)
|
||||
* .threshold(128, { grayscale: false }) // converter bright pixels to white
|
||||
* .unflatten()
|
||||
* .toBuffer();
|
||||
*/
|
||||
function unflatten (options) {
|
||||
this.options.unflatten = is.bool(options) ? options : true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a gamma correction by reducing the encoding (darken) pre-resize at a factor of `1/gamma`
|
||||
* then increasing the encoding (brighten) post-resize at a factor of `gamma`.
|
||||
@ -875,6 +894,7 @@ module.exports = function (Sharp) {
|
||||
median,
|
||||
blur,
|
||||
flatten,
|
||||
unflatten,
|
||||
gamma,
|
||||
negate,
|
||||
normalise,
|
||||
|
@ -342,6 +342,19 @@ namespace sharp {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unflatten
|
||||
*/
|
||||
VImage Unflatten(VImage image) {
|
||||
if (HasAlpha(image)) {
|
||||
VImage alpha = image[image.bands() - 1];
|
||||
VImage noAlpha = RemoveAlpha(image);
|
||||
return noAlpha.bandjoin(alpha & (noAlpha.colourspace(VIPS_INTERPRETATION_B_W) < 255));
|
||||
} else {
|
||||
return image.bandjoin(image.colourspace(VIPS_INTERPRETATION_B_W) < 255);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure the image is in a given colourspace
|
||||
*/
|
||||
|
@ -86,6 +86,11 @@ namespace sharp {
|
||||
*/
|
||||
VImage Linear(VImage image, std::vector<double> const a, std::vector<double> const b);
|
||||
|
||||
/*
|
||||
* Unflatten
|
||||
*/
|
||||
VImage Unflatten(VImage image);
|
||||
|
||||
/*
|
||||
* Recomb with a Matrix of the given bands/channel size.
|
||||
* Eg. RGB will be a 3x3 matrix.
|
||||
|
@ -550,7 +550,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
||||
if (baton->medianSize > 0) {
|
||||
image = image.median(baton->medianSize);
|
||||
}
|
||||
|
||||
// Threshold - must happen before blurring, due to the utility of blurring after thresholding
|
||||
// Threshold - must happen before unflatten to enable non-white unflattening
|
||||
if (baton->threshold != 0) {
|
||||
image = sharp::Threshold(image, baton->threshold, baton->thresholdGrayscale);
|
||||
}
|
||||
@ -560,6 +562,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
||||
image = sharp::Blur(image, baton->blurSigma);
|
||||
}
|
||||
|
||||
// Unflatten the image
|
||||
if (baton->unflatten) {
|
||||
image = sharp::Unflatten(image);
|
||||
}
|
||||
|
||||
// Convolve
|
||||
if (shouldConv) {
|
||||
image = sharp::Convolve(image,
|
||||
@ -1460,6 +1467,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
||||
// Operators
|
||||
baton->flatten = sharp::AttrAsBool(options, "flatten");
|
||||
baton->flattenBackground = sharp::AttrAsVectorOfDouble(options, "flattenBackground");
|
||||
baton->unflatten = sharp::AttrAsBool(options, "unflatten");
|
||||
baton->negate = sharp::AttrAsBool(options, "negate");
|
||||
baton->negateAlpha = sharp::AttrAsBool(options, "negateAlpha");
|
||||
baton->blurSigma = sharp::AttrAsDouble(options, "blurSigma");
|
||||
|
@ -73,6 +73,7 @@ struct PipelineBaton {
|
||||
double tintB;
|
||||
bool flatten;
|
||||
std::vector<double> flattenBackground;
|
||||
bool unflatten;
|
||||
bool negate;
|
||||
bool negateAlpha;
|
||||
double blurSigma;
|
||||
@ -239,6 +240,7 @@ struct PipelineBaton {
|
||||
tintB(128.0),
|
||||
flatten(false),
|
||||
flattenBackground{ 0.0, 0.0, 0.0 },
|
||||
unflatten(false),
|
||||
negate(false),
|
||||
negateAlpha(true),
|
||||
blurSigma(0.0),
|
||||
|
BIN
test/fixtures/expected/unflatten-flag-white-transparent.png
vendored
Normal file
BIN
test/fixtures/expected/unflatten-flag-white-transparent.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
test/fixtures/expected/unflatten-swiss.png
vendored
Normal file
BIN
test/fixtures/expected/unflatten-swiss.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
BIN
test/fixtures/expected/unflatten-white-transparent.png
vendored
Normal file
BIN
test/fixtures/expected/unflatten-white-transparent.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 225 KiB |
37
test/unit/unflatten.js
Normal file
37
test/unit/unflatten.js
Normal file
@ -0,0 +1,37 @@
|
||||
'use strict';
|
||||
|
||||
const sharp = require('../../');
|
||||
const fixtures = require('../fixtures');
|
||||
|
||||
// const assert = require('assert');
|
||||
|
||||
describe('Unflatten', function () {
|
||||
it('unflatten white background', function (done) {
|
||||
sharp(fixtures.inputPng).unflatten()
|
||||
.toBuffer(function (err, data) {
|
||||
if (err) throw err;
|
||||
fixtures.assertSimilar(fixtures.expected('unflatten-white-transparent.png'), data, { threshold: 0 }, done);
|
||||
});
|
||||
});
|
||||
it('unflatten transparent image', function (done) {
|
||||
sharp(fixtures.inputPngTrimSpecificColourIncludeAlpha).unflatten()
|
||||
.toBuffer(function (err, data) {
|
||||
if (err) throw err;
|
||||
fixtures.assertSimilar(fixtures.expected('unflatten-flag-white-transparent.png'), data, { threshold: 0 }, done);
|
||||
});
|
||||
});
|
||||
it('unflatten using threshold', function (done) {
|
||||
sharp(fixtures.inputPngPalette).unflatten(true).threshold(128, { grayscale: false })
|
||||
.toBuffer(function (err, data) {
|
||||
if (err) throw err;
|
||||
fixtures.assertSimilar(fixtures.expected('unflatten-swiss.png'), data, { threshold: 1 }, done);
|
||||
});
|
||||
});
|
||||
it('no unflatten', function (done) {
|
||||
sharp(fixtures.inputPng).unflatten(false)
|
||||
.toBuffer(function (err, data) {
|
||||
if (err) throw err;
|
||||
fixtures.assertSimilar(fixtures.inputPng, data, { threshold: 0 }, done);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user