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",
|
||||
"version": "0.11.0",
|
||||
"version": "0.11.1",
|
||||
"author": "Lovell Fuller <npm@lovell.info>",
|
||||
"contributors": [
|
||||
"Pierre Inglebert <pierre.inglebert@gmail.com>",
|
||||
@ -51,7 +51,7 @@
|
||||
"semver": "^5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"async": "^1.3.0",
|
||||
"async": "^1.4.2",
|
||||
"coveralls": "^2.11.2",
|
||||
"exif-reader": "1.0.0",
|
||||
"icc": "^0.0.2",
|
||||
|
@ -445,7 +445,7 @@ class PipelineWorker : public NanAsyncWorker {
|
||||
}
|
||||
|
||||
// Gamma encoding (darken)
|
||||
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
||||
if (baton->gamma >= 1 && baton->gamma <= 3 && !HasAlpha(image)) {
|
||||
VipsImage *gammaEncoded;
|
||||
if (vips_gamma(image, &gammaEncoded, "exponent", 1.0 / baton->gamma, NULL)) {
|
||||
return Error();
|
||||
@ -493,11 +493,9 @@ class PipelineWorker : public NanAsyncWorker {
|
||||
}
|
||||
|
||||
bool shouldAffineTransform = xresidual != 0.0 || yresidual != 0.0;
|
||||
bool shouldBlur = baton->blurSigma != 0.0;
|
||||
bool shouldSharpen = baton->sharpenRadius != 0;
|
||||
bool shouldTransform = shouldAffineTransform || shouldBlur || shouldSharpen;
|
||||
bool willConvolve = baton->blurSigma > 0.0 || baton->sharpenRadius > 0;
|
||||
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
|
||||
// dark fringing around bright pixels
|
||||
@ -681,7 +679,7 @@ class PipelineWorker : public NanAsyncWorker {
|
||||
}
|
||||
|
||||
// Blur
|
||||
if (shouldBlur) {
|
||||
if (baton->blurSigma != 0.0) {
|
||||
VipsImage *blurred;
|
||||
if (Blur(hook, image, &blurred, baton->blurSigma)) {
|
||||
return Error();
|
||||
@ -690,7 +688,7 @@ class PipelineWorker : public NanAsyncWorker {
|
||||
}
|
||||
|
||||
// Sharpen
|
||||
if (shouldSharpen) {
|
||||
if (baton->sharpenRadius != 0) {
|
||||
VipsImage *sharpened;
|
||||
if (Sharpen(hook, image, &sharpened, baton->sharpenRadius, baton->sharpenFlat, baton->sharpenJagged)) {
|
||||
return Error();
|
||||
@ -698,25 +696,6 @@ class PipelineWorker : public NanAsyncWorker {
|
||||
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
|
||||
if (hasOverlay) {
|
||||
VipsImage *overlayImage = NULL;
|
||||
@ -789,6 +768,25 @@ class PipelineWorker : public NanAsyncWorker {
|
||||
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
|
||||
if (image->Type != VIPS_INTERPRETATION_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) {
|
||||
sharp(fixtures.inputJpgWithGammaHoliness)
|
||||
.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) {
|
||||
sharp(fixtures.inputJpgWithGammaHoliness)
|
||||
.resize(129, 111)
|
||||
.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) {
|
||||
sharp(fixtures.inputJpgWithGammaHoliness)
|
||||
.resize(129, 111)
|
||||
.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) {
|
||||
var isValid = true;
|
||||
try {
|
||||
it('alpha transparency', function(done) {
|
||||
sharp(fixtures.inputPngOverlayLayer1)
|
||||
.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);
|
||||
} catch (err) {
|
||||
isValid = false;
|
||||
}
|
||||
assert.strictEqual(false, isValid);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user