mirror of
https://github.com/lovell/sharp.git
synced 2025-07-14 12:50:12 +02:00
Gamma correction and premultiply do not mix
Skip premultiply for fast blur/sharpen Automate gamma correction tests
This commit is contained in:
parent
9c83d98bbb
commit
36ac8828f2
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sharp",
|
"name": "sharp",
|
||||||
"version": "0.11.0",
|
"version": "0.11.1",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Pierre Inglebert <pierre.inglebert@gmail.com>",
|
"Pierre Inglebert <pierre.inglebert@gmail.com>",
|
||||||
@ -51,7 +51,7 @@
|
|||||||
"semver": "^5.0.1"
|
"semver": "^5.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"async": "^1.3.0",
|
"async": "^1.4.2",
|
||||||
"coveralls": "^2.11.2",
|
"coveralls": "^2.11.2",
|
||||||
"exif-reader": "1.0.0",
|
"exif-reader": "1.0.0",
|
||||||
"icc": "^0.0.2",
|
"icc": "^0.0.2",
|
||||||
|
@ -445,7 +445,7 @@ class PipelineWorker : public NanAsyncWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Gamma encoding (darken)
|
// Gamma encoding (darken)
|
||||||
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
if (baton->gamma >= 1 && baton->gamma <= 3 && !HasAlpha(image)) {
|
||||||
VipsImage *gammaEncoded;
|
VipsImage *gammaEncoded;
|
||||||
if (vips_gamma(image, &gammaEncoded, "exponent", 1.0 / baton->gamma, NULL)) {
|
if (vips_gamma(image, &gammaEncoded, "exponent", 1.0 / baton->gamma, NULL)) {
|
||||||
return Error();
|
return Error();
|
||||||
@ -493,11 +493,9 @@ class PipelineWorker : public NanAsyncWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool shouldAffineTransform = xresidual != 0.0 || yresidual != 0.0;
|
bool shouldAffineTransform = xresidual != 0.0 || yresidual != 0.0;
|
||||||
bool shouldBlur = baton->blurSigma != 0.0;
|
bool willConvolve = baton->blurSigma > 0.0 || baton->sharpenRadius > 0;
|
||||||
bool shouldSharpen = baton->sharpenRadius != 0;
|
|
||||||
bool shouldTransform = shouldAffineTransform || shouldBlur || shouldSharpen;
|
|
||||||
bool hasOverlay = !baton->overlayPath.empty();
|
bool hasOverlay = !baton->overlayPath.empty();
|
||||||
bool shouldPremultiplyAlpha = HasAlpha(image) && image->Bands == 4 && (shouldTransform || hasOverlay);
|
bool shouldPremultiplyAlpha = HasAlpha(image) && (shouldAffineTransform || willConvolve || hasOverlay);
|
||||||
|
|
||||||
// Premultiply image alpha channel before all transformations to avoid
|
// Premultiply image alpha channel before all transformations to avoid
|
||||||
// dark fringing around bright pixels
|
// dark fringing around bright pixels
|
||||||
@ -681,7 +679,7 @@ class PipelineWorker : public NanAsyncWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Blur
|
// Blur
|
||||||
if (shouldBlur) {
|
if (baton->blurSigma != 0.0) {
|
||||||
VipsImage *blurred;
|
VipsImage *blurred;
|
||||||
if (Blur(hook, image, &blurred, baton->blurSigma)) {
|
if (Blur(hook, image, &blurred, baton->blurSigma)) {
|
||||||
return Error();
|
return Error();
|
||||||
@ -690,7 +688,7 @@ class PipelineWorker : public NanAsyncWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sharpen
|
// Sharpen
|
||||||
if (shouldSharpen) {
|
if (baton->sharpenRadius != 0) {
|
||||||
VipsImage *sharpened;
|
VipsImage *sharpened;
|
||||||
if (Sharpen(hook, image, &sharpened, baton->sharpenRadius, baton->sharpenFlat, baton->sharpenJagged)) {
|
if (Sharpen(hook, image, &sharpened, baton->sharpenRadius, baton->sharpenFlat, baton->sharpenJagged)) {
|
||||||
return Error();
|
return Error();
|
||||||
@ -698,25 +696,6 @@ class PipelineWorker : public NanAsyncWorker {
|
|||||||
image = sharpened;
|
image = sharpened;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gamma decoding (brighten)
|
|
||||||
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
|
||||||
VipsImage *gammaDecoded;
|
|
||||||
if (vips_gamma(image, &gammaDecoded, "exponent", baton->gamma, NULL)) {
|
|
||||||
return Error();
|
|
||||||
}
|
|
||||||
vips_object_local(hook, gammaDecoded);
|
|
||||||
image = gammaDecoded;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply normalization - stretch luminance to cover full dynamic range
|
|
||||||
if (baton->normalize) {
|
|
||||||
VipsImage *normalized;
|
|
||||||
if (Normalize(hook, image, &normalized)) {
|
|
||||||
return Error();
|
|
||||||
}
|
|
||||||
image = normalized;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Composite with overlay, if present
|
// Composite with overlay, if present
|
||||||
if (hasOverlay) {
|
if (hasOverlay) {
|
||||||
VipsImage *overlayImage = NULL;
|
VipsImage *overlayImage = NULL;
|
||||||
@ -789,6 +768,25 @@ class PipelineWorker : public NanAsyncWorker {
|
|||||||
image = imageUnpremultiplied;
|
image = imageUnpremultiplied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gamma decoding (brighten)
|
||||||
|
if (baton->gamma >= 1 && baton->gamma <= 3 && !HasAlpha(image)) {
|
||||||
|
VipsImage *gammaDecoded;
|
||||||
|
if (vips_gamma(image, &gammaDecoded, "exponent", baton->gamma, NULL)) {
|
||||||
|
return Error();
|
||||||
|
}
|
||||||
|
vips_object_local(hook, gammaDecoded);
|
||||||
|
image = gammaDecoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply normalization - stretch luminance to cover full dynamic range
|
||||||
|
if (baton->normalize) {
|
||||||
|
VipsImage *normalized;
|
||||||
|
if (Normalize(hook, image, &normalized)) {
|
||||||
|
return Error();
|
||||||
|
}
|
||||||
|
image = normalized;
|
||||||
|
}
|
||||||
|
|
||||||
// Convert image to sRGB, if not already
|
// Convert image to sRGB, if not already
|
||||||
if (image->Type != VIPS_INTERPRETATION_sRGB) {
|
if (image->Type != VIPS_INTERPRETATION_sRGB) {
|
||||||
// Switch interpretation to sRGB
|
// Switch interpretation to sRGB
|
||||||
|
BIN
test/fixtures/expected/gamma-0.0.jpg
vendored
Normal file
BIN
test/fixtures/expected/gamma-0.0.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 377 B |
BIN
test/fixtures/expected/gamma-2.2.jpg
vendored
Normal file
BIN
test/fixtures/expected/gamma-2.2.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
BIN
test/fixtures/expected/gamma-3.0.jpg
vendored
Normal file
BIN
test/fixtures/expected/gamma-3.0.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
BIN
test/fixtures/expected/gamma-alpha.jpg
vendored
Normal file
BIN
test/fixtures/expected/gamma-alpha.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
@ -12,32 +12,53 @@ describe('Gamma correction', function() {
|
|||||||
it('value of 0.0 (disabled)', function(done) {
|
it('value of 0.0 (disabled)', function(done) {
|
||||||
sharp(fixtures.inputJpgWithGammaHoliness)
|
sharp(fixtures.inputJpgWithGammaHoliness)
|
||||||
.resize(129, 111)
|
.resize(129, 111)
|
||||||
.toFile(fixtures.path('output.gamma-0.0.jpg'), done);
|
.toBuffer(function(err, data, info) {
|
||||||
|
assert.strictEqual('jpeg', info.format);
|
||||||
|
assert.strictEqual(129, info.width);
|
||||||
|
assert.strictEqual(111, info.height);
|
||||||
|
fixtures.assertSimilar(fixtures.expected('gamma-0.0.jpg'), data, done);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('value of 2.2 (default)', function(done) {
|
it('value of 2.2 (default)', function(done) {
|
||||||
sharp(fixtures.inputJpgWithGammaHoliness)
|
sharp(fixtures.inputJpgWithGammaHoliness)
|
||||||
.resize(129, 111)
|
.resize(129, 111)
|
||||||
.gamma()
|
.gamma()
|
||||||
.toFile(fixtures.path('output.gamma-2.2.jpg'), done);
|
.toBuffer(function(err, data, info) {
|
||||||
|
assert.strictEqual('jpeg', info.format);
|
||||||
|
assert.strictEqual(129, info.width);
|
||||||
|
assert.strictEqual(111, info.height);
|
||||||
|
fixtures.assertSimilar(fixtures.expected('gamma-2.2.jpg'), data, done);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('value of 3.0', function(done) {
|
it('value of 3.0', function(done) {
|
||||||
sharp(fixtures.inputJpgWithGammaHoliness)
|
sharp(fixtures.inputJpgWithGammaHoliness)
|
||||||
.resize(129, 111)
|
.resize(129, 111)
|
||||||
.gamma(3)
|
.gamma(3)
|
||||||
.toFile(fixtures.path('output.gamma-3.0.jpg'), done);
|
.toBuffer(function(err, data, info) {
|
||||||
|
assert.strictEqual('jpeg', info.format);
|
||||||
|
assert.strictEqual(129, info.width);
|
||||||
|
assert.strictEqual(111, info.height);
|
||||||
|
fixtures.assertSimilar(fixtures.expected('gamma-3.0.jpg'), data, done);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid value', function(done) {
|
it('alpha transparency', function(done) {
|
||||||
var isValid = true;
|
sharp(fixtures.inputPngOverlayLayer1)
|
||||||
try {
|
.resize(320)
|
||||||
|
.gamma()
|
||||||
|
.toBuffer(function(err, data, info) {
|
||||||
|
assert.strictEqual('png', info.format);
|
||||||
|
assert.strictEqual(320, info.width);
|
||||||
|
fixtures.assertSimilar(fixtures.expected('gamma-alpha.jpg'), data, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invalid value', function() {
|
||||||
|
assert.throws(function() {
|
||||||
sharp(fixtures.inputJpgWithGammaHoliness).gamma(4);
|
sharp(fixtures.inputJpgWithGammaHoliness).gamma(4);
|
||||||
} catch (err) {
|
});
|
||||||
isValid = false;
|
|
||||||
}
|
|
||||||
assert.strictEqual(false, isValid);
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user