Allow separate parameters for gamma encoding and decoding (#1439)

This commit is contained in:
Daiz 2018-11-11 11:15:38 +02:00 committed by Lovell Fuller
parent 1fa388370e
commit a48f8fbb61
8 changed files with 41 additions and 5 deletions

View File

@ -134,6 +134,7 @@ when applying a gamma correction.
### Parameters ### Parameters
- `gamma` **[Number][1]** value between 1.0 and 3.0. (optional, default `2.2`) - `gamma` **[Number][1]** value between 1.0 and 3.0. (optional, default `2.2`)
- `gammaOut` ** [Number][1]** value between 1.0 and 3.0. (optional, defaults to same as `gamma`)
- Throws **[Error][5]** Invalid parameters - Throws **[Error][5]** Invalid parameters

View File

@ -14,6 +14,10 @@ Requires libvips v8.7.0.
[#1438](https://github.com/lovell/sharp/pull/1438) [#1438](https://github.com/lovell/sharp/pull/1438)
[@Daiz](https://github.com/Daiz) [@Daiz](https://github.com/Daiz)
* Add support for different output gamma from what is used for scaling.
[#1439](https://github.com/lovell/sharp/pull/1439)
[@Daiz](https://github.com/Daiz)
#### v0.21.0 - 4<sup>th</sup> October 2018 #### v0.21.0 - 4<sup>th</sup> October 2018
* Deprecate the following resize-related functions: * Deprecate the following resize-related functions:

View File

@ -136,6 +136,7 @@ const Sharp = function (input, options) {
thresholdGrayscale: true, thresholdGrayscale: true,
trimThreshold: 0, trimThreshold: 0,
gamma: 0, gamma: 0,
gammaOut: 0,
greyscale: false, greyscale: false,
normalise: 0, normalise: 0,
booleanBufferIn: null, booleanBufferIn: null,

View File

@ -189,12 +189,13 @@ function flatten (options) {
* then increasing the encoding (brighten) post-resize at a factor of `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.
* JPEG and WebP input images will not take advantage of the shrink-on-load performance optimisation * JPEG and WebP input images will not take advantage of the shrink-on-load performance optimisation
* when applying a gamma correction. * when applying a gamma correction. Supply a second argument to use a different output gamma value, otherwise the first value is used in both cases.
* @param {Number} [gamma=2.2] value between 1.0 and 3.0. * @param {Number} [gamma=2.2] value between 1.0 and 3.0.
* @param {Number} [gammaOut] value between 1.0 and 3.0. Defaults to same as gamma.
* @returns {Sharp} * @returns {Sharp}
* @throws {Error} Invalid parameters * @throws {Error} Invalid parameters
*/ */
function gamma (gamma) { function gamma (gamma, gammaOut) {
if (!is.defined(gamma)) { if (!is.defined(gamma)) {
// Default gamma correction of 2.2 (sRGB) // Default gamma correction of 2.2 (sRGB)
this.options.gamma = 2.2; this.options.gamma = 2.2;
@ -203,6 +204,14 @@ function gamma (gamma) {
} else { } else {
throw new Error('Invalid gamma correction (1.0 to 3.0) ' + gamma); throw new Error('Invalid gamma correction (1.0 to 3.0) ' + gamma);
} }
if (!is.defined(gammaOut)) {
// Default gamma correction for output is same as input
this.options.gammaOut = this.options.gamma;
} else if (is.number(gammaOut) && is.inRange(gammaOut, 1, 3)) {
this.options.gammaOut = gammaOut;
} else {
throw new Error('Invalid post gamma correction (1.0 to 3.0) ' + gammaOut);
}
return this; return this;
} }

View File

@ -612,8 +612,8 @@ class PipelineWorker : public Nan::AsyncWorker {
baton->premultiplied = shouldPremultiplyAlpha; baton->premultiplied = shouldPremultiplyAlpha;
// Gamma decoding (brighten) // Gamma decoding (brighten)
if (baton->gamma >= 1 && baton->gamma <= 3) { if (baton->gammaOut >= 1 && baton->gammaOut <= 3) {
image = sharp::Gamma(image, baton->gamma); image = sharp::Gamma(image, baton->gammaOut);
} }
// Linear adjustment (a * in + b) // Linear adjustment (a * in + b)
@ -1193,6 +1193,7 @@ NAN_METHOD(pipeline) {
baton->thresholdGrayscale = AttrTo<bool>(options, "thresholdGrayscale"); baton->thresholdGrayscale = AttrTo<bool>(options, "thresholdGrayscale");
baton->trimThreshold = AttrTo<double>(options, "trimThreshold"); baton->trimThreshold = AttrTo<double>(options, "trimThreshold");
baton->gamma = AttrTo<double>(options, "gamma"); baton->gamma = AttrTo<double>(options, "gamma");
baton->gammaOut = AttrTo<double>(options, "gammaOut");
baton->linearA = AttrTo<double>(options, "linearA"); baton->linearA = AttrTo<double>(options, "linearA");
baton->linearB = AttrTo<double>(options, "linearB"); baton->linearB = AttrTo<double>(options, "linearB");
baton->greyscale = AttrTo<bool>(options, "greyscale"); baton->greyscale = AttrTo<bool>(options, "greyscale");

View File

@ -87,6 +87,7 @@ struct PipelineBaton {
double linearA; double linearA;
double linearB; double linearB;
double gamma; double gamma;
double gammaOut;
bool greyscale; bool greyscale;
bool normalise; bool normalise;
bool useExifOrientation; bool useExifOrientation;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -44,6 +44,19 @@ describe('Gamma correction', function () {
}); });
}); });
it('input value of 2.2, output value of 3.0', function (done) {
sharp(fixtures.inputJpgWithGammaHoliness)
.resize(129, 111)
.gamma(2.2, 3.0)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
assert.strictEqual(129, info.width);
assert.strictEqual(111, info.height);
fixtures.assertSimilar(fixtures.expected('gamma-in-2.2-out-3.0.jpg'), data, { threshold: 6 }, done);
});
});
it('alpha transparency', function (done) { it('alpha transparency', function (done) {
sharp(fixtures.inputPngOverlayLayer1) sharp(fixtures.inputPngOverlayLayer1)
.resize(320) .resize(320)
@ -57,9 +70,15 @@ describe('Gamma correction', function () {
}); });
}); });
it('invalid value', function () { it('invalid first parameter value', function () {
assert.throws(function () { assert.throws(function () {
sharp(fixtures.inputJpgWithGammaHoliness).gamma(4); sharp(fixtures.inputJpgWithGammaHoliness).gamma(4);
}); });
}); });
it('invalid second parameter value', function () {
assert.throws(function () {
sharp(fixtures.inputJpgWithGammaHoliness).gamma(2.2, 4);
});
});
}); });