diff --git a/docs/api-operation.md b/docs/api-operation.md
index 5422a194..0fc3a8c6 100644
--- a/docs/api-operation.md
+++ b/docs/api-operation.md
@@ -134,6 +134,7 @@ when applying a gamma correction.
### Parameters
- `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
diff --git a/docs/changelog.md b/docs/changelog.md
index 5a54e0af..3f9b4aa4 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -14,6 +14,10 @@ Requires libvips v8.7.0.
[#1438](https://github.com/lovell/sharp/pull/1438)
[@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 - 4th October 2018
* Deprecate the following resize-related functions:
diff --git a/lib/constructor.js b/lib/constructor.js
index 24a2eb69..130f3bab 100644
--- a/lib/constructor.js
+++ b/lib/constructor.js
@@ -136,6 +136,7 @@ const Sharp = function (input, options) {
thresholdGrayscale: true,
trimThreshold: 0,
gamma: 0,
+ gammaOut: 0,
greyscale: false,
normalise: 0,
booleanBufferIn: null,
diff --git a/lib/operation.js b/lib/operation.js
index 4eb86f5f..1f03b64d 100644
--- a/lib/operation.js
+++ b/lib/operation.js
@@ -189,12 +189,13 @@ function flatten (options) {
* 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.
* 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} [gammaOut] value between 1.0 and 3.0. Defaults to same as gamma.
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
-function gamma (gamma) {
+function gamma (gamma, gammaOut) {
if (!is.defined(gamma)) {
// Default gamma correction of 2.2 (sRGB)
this.options.gamma = 2.2;
@@ -203,6 +204,14 @@ function gamma (gamma) {
} else {
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;
}
diff --git a/src/pipeline.cc b/src/pipeline.cc
index 97597b48..d230b1e4 100644
--- a/src/pipeline.cc
+++ b/src/pipeline.cc
@@ -612,8 +612,8 @@ class PipelineWorker : public Nan::AsyncWorker {
baton->premultiplied = shouldPremultiplyAlpha;
// Gamma decoding (brighten)
- if (baton->gamma >= 1 && baton->gamma <= 3) {
- image = sharp::Gamma(image, baton->gamma);
+ if (baton->gammaOut >= 1 && baton->gammaOut <= 3) {
+ image = sharp::Gamma(image, baton->gammaOut);
}
// Linear adjustment (a * in + b)
@@ -1193,6 +1193,7 @@ NAN_METHOD(pipeline) {
baton->thresholdGrayscale = AttrTo(options, "thresholdGrayscale");
baton->trimThreshold = AttrTo(options, "trimThreshold");
baton->gamma = AttrTo(options, "gamma");
+ baton->gammaOut = AttrTo(options, "gammaOut");
baton->linearA = AttrTo(options, "linearA");
baton->linearB = AttrTo(options, "linearB");
baton->greyscale = AttrTo(options, "greyscale");
diff --git a/src/pipeline.h b/src/pipeline.h
index cd763a86..fb18ab2b 100644
--- a/src/pipeline.h
+++ b/src/pipeline.h
@@ -87,6 +87,7 @@ struct PipelineBaton {
double linearA;
double linearB;
double gamma;
+ double gammaOut;
bool greyscale;
bool normalise;
bool useExifOrientation;
diff --git a/test/fixtures/expected/gamma-in-2.2-out-3.0.jpg b/test/fixtures/expected/gamma-in-2.2-out-3.0.jpg
new file mode 100644
index 00000000..50ddb9d1
Binary files /dev/null and b/test/fixtures/expected/gamma-in-2.2-out-3.0.jpg differ
diff --git a/test/unit/gamma.js b/test/unit/gamma.js
index b5c56e1b..da8feea9 100644
--- a/test/unit/gamma.js
+++ b/test/unit/gamma.js
@@ -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) {
sharp(fixtures.inputPngOverlayLayer1)
.resize(320)
@@ -57,9 +70,15 @@ describe('Gamma correction', function () {
});
});
- it('invalid value', function () {
+ it('invalid first parameter value', function () {
assert.throws(function () {
sharp(fixtures.inputJpgWithGammaHoliness).gamma(4);
});
});
+
+ it('invalid second parameter value', function () {
+ assert.throws(function () {
+ sharp(fixtures.inputJpgWithGammaHoliness).gamma(2.2, 4);
+ });
+ });
});