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,
|
tintB: 128,
|
||||||
flatten: false,
|
flatten: false,
|
||||||
flattenBackground: [0, 0, 0],
|
flattenBackground: [0, 0, 0],
|
||||||
|
unflatten: false,
|
||||||
negate: false,
|
negate: false,
|
||||||
negateAlpha: true,
|
negateAlpha: true,
|
||||||
medianSize: 0,
|
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;
|
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.
|
* 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.
|
* This can improve the perceived brightness of a resized image in non-linear colour spaces.
|
||||||
|
@ -405,6 +405,25 @@ function flatten (options) {
|
|||||||
return this;
|
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`
|
* 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`.
|
* then increasing the encoding (brighten) post-resize at a factor of `gamma`.
|
||||||
@ -875,6 +894,7 @@ module.exports = function (Sharp) {
|
|||||||
median,
|
median,
|
||||||
blur,
|
blur,
|
||||||
flatten,
|
flatten,
|
||||||
|
unflatten,
|
||||||
gamma,
|
gamma,
|
||||||
negate,
|
negate,
|
||||||
normalise,
|
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
|
* 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);
|
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.
|
* Recomb with a Matrix of the given bands/channel size.
|
||||||
* Eg. RGB will be a 3x3 matrix.
|
* Eg. RGB will be a 3x3 matrix.
|
||||||
|
@ -550,7 +550,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (baton->medianSize > 0) {
|
if (baton->medianSize > 0) {
|
||||||
image = image.median(baton->medianSize);
|
image = image.median(baton->medianSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Threshold - must happen before blurring, due to the utility of blurring after thresholding
|
// 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) {
|
if (baton->threshold != 0) {
|
||||||
image = sharp::Threshold(image, baton->threshold, baton->thresholdGrayscale);
|
image = sharp::Threshold(image, baton->threshold, baton->thresholdGrayscale);
|
||||||
}
|
}
|
||||||
@ -560,6 +562,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
image = sharp::Blur(image, baton->blurSigma);
|
image = sharp::Blur(image, baton->blurSigma);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unflatten the image
|
||||||
|
if (baton->unflatten) {
|
||||||
|
image = sharp::Unflatten(image);
|
||||||
|
}
|
||||||
|
|
||||||
// Convolve
|
// Convolve
|
||||||
if (shouldConv) {
|
if (shouldConv) {
|
||||||
image = sharp::Convolve(image,
|
image = sharp::Convolve(image,
|
||||||
@ -1460,6 +1467,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
// Operators
|
// Operators
|
||||||
baton->flatten = sharp::AttrAsBool(options, "flatten");
|
baton->flatten = sharp::AttrAsBool(options, "flatten");
|
||||||
baton->flattenBackground = sharp::AttrAsVectorOfDouble(options, "flattenBackground");
|
baton->flattenBackground = sharp::AttrAsVectorOfDouble(options, "flattenBackground");
|
||||||
|
baton->unflatten = sharp::AttrAsBool(options, "unflatten");
|
||||||
baton->negate = sharp::AttrAsBool(options, "negate");
|
baton->negate = sharp::AttrAsBool(options, "negate");
|
||||||
baton->negateAlpha = sharp::AttrAsBool(options, "negateAlpha");
|
baton->negateAlpha = sharp::AttrAsBool(options, "negateAlpha");
|
||||||
baton->blurSigma = sharp::AttrAsDouble(options, "blurSigma");
|
baton->blurSigma = sharp::AttrAsDouble(options, "blurSigma");
|
||||||
|
@ -73,6 +73,7 @@ struct PipelineBaton {
|
|||||||
double tintB;
|
double tintB;
|
||||||
bool flatten;
|
bool flatten;
|
||||||
std::vector<double> flattenBackground;
|
std::vector<double> flattenBackground;
|
||||||
|
bool unflatten;
|
||||||
bool negate;
|
bool negate;
|
||||||
bool negateAlpha;
|
bool negateAlpha;
|
||||||
double blurSigma;
|
double blurSigma;
|
||||||
@ -239,6 +240,7 @@ struct PipelineBaton {
|
|||||||
tintB(128.0),
|
tintB(128.0),
|
||||||
flatten(false),
|
flatten(false),
|
||||||
flattenBackground{ 0.0, 0.0, 0.0 },
|
flattenBackground{ 0.0, 0.0, 0.0 },
|
||||||
|
unflatten(false),
|
||||||
negate(false),
|
negate(false),
|
||||||
negateAlpha(true),
|
negateAlpha(true),
|
||||||
blurSigma(0.0),
|
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