mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 18:40:16 +02:00
Implements negation.
This commit is contained in:
parent
5dfeaa9fd1
commit
33a175eafb
@ -272,6 +272,10 @@ The default background is `{r: 0, g: 0, b: 0, a: 1}`, black without transparency
|
||||
|
||||
Merge alpha transparency channel, if any, with `background`.
|
||||
|
||||
#### negate()
|
||||
|
||||
Produces the "negative" of the image. White => Black, Black => White, Blue => Yellow, etc.
|
||||
|
||||
#### rotate([angle])
|
||||
|
||||
Rotate the output image by either an explicit angle or auto-orient based on the EXIF `Orientation` tag.
|
||||
|
6
index.js
6
index.js
@ -58,6 +58,7 @@ var Sharp = function(input) {
|
||||
// operations
|
||||
background: [0, 0, 0, 255],
|
||||
flatten: false,
|
||||
negate: false,
|
||||
blurSigma: 0,
|
||||
sharpenRadius: 0,
|
||||
sharpenFlat: 1,
|
||||
@ -215,6 +216,11 @@ Sharp.prototype.flatten = function(flatten) {
|
||||
return this;
|
||||
};
|
||||
|
||||
Sharp.prototype.negate = function(negate) {
|
||||
this.options.negate = (typeof negate === 'boolean') ? negate : true;
|
||||
return this;
|
||||
};
|
||||
|
||||
Sharp.prototype.overlayWith = function(overlayPath) {
|
||||
if (typeof overlayPath !== 'string') {
|
||||
throw new Error('The overlay path must be a string');
|
||||
|
@ -100,6 +100,7 @@ struct PipelineBaton {
|
||||
std::string interpolator;
|
||||
double background[4];
|
||||
bool flatten;
|
||||
bool negate;
|
||||
double blurSigma;
|
||||
int sharpenRadius;
|
||||
double sharpenFlat;
|
||||
@ -138,6 +139,7 @@ struct PipelineBaton {
|
||||
canvas(Canvas::CROP),
|
||||
gravity(0),
|
||||
flatten(false),
|
||||
negate(false),
|
||||
blurSigma(0.0),
|
||||
sharpenRadius(0),
|
||||
sharpenFlat(1.0),
|
||||
@ -451,6 +453,16 @@ class PipelineWorker : public AsyncWorker {
|
||||
image = flattened;
|
||||
}
|
||||
|
||||
// Negate the colors in the image.
|
||||
if (baton->negate) {
|
||||
VipsImage *negated;
|
||||
if (vips_invert(image, &negated, nullptr)) {
|
||||
return Error();
|
||||
}
|
||||
vips_object_local(hook, negated);
|
||||
image = negated;
|
||||
}
|
||||
|
||||
// Gamma encoding (darken)
|
||||
if (baton->gamma >= 1 && baton->gamma <= 3 && !HasAlpha(image)) {
|
||||
VipsImage *gammaEncoded;
|
||||
@ -1212,6 +1224,7 @@ NAN_METHOD(pipeline) {
|
||||
baton->interpolator = *Utf8String(Get(options, New("interpolator").ToLocalChecked()).ToLocalChecked());
|
||||
// Operators
|
||||
baton->flatten = To<bool>(Get(options, New("flatten").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->negate = To<bool>(Get(options, New("negate").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->blurSigma = To<double>(Get(options, New("blurSigma").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->sharpenRadius = To<int32_t>(Get(options, New("sharpenRadius").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->sharpenFlat = To<double>(Get(options, New("sharpenFlat").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
|
BIN
test/fixtures/expected/negate-alpha.png
vendored
Normal file
BIN
test/fixtures/expected/negate-alpha.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
test/fixtures/expected/negate-trans.png
vendored
Normal file
BIN
test/fixtures/expected/negate-trans.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.0 KiB |
BIN
test/fixtures/expected/negate-trans.webp
vendored
Normal file
BIN
test/fixtures/expected/negate-trans.webp
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
BIN
test/fixtures/expected/negate.jpg
vendored
Normal file
BIN
test/fixtures/expected/negate.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
test/fixtures/expected/negate.png
vendored
Normal file
BIN
test/fixtures/expected/negate.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
BIN
test/fixtures/expected/negate.webp
vendored
Normal file
BIN
test/fixtures/expected/negate.webp
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
107
test/unit/negate.js
Normal file
107
test/unit/negate.js
Normal file
@ -0,0 +1,107 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var sharp = require('../../index');
|
||||
var fixtures = require('../fixtures');
|
||||
|
||||
sharp.cache(0);
|
||||
|
||||
describe('Negate', function() {
|
||||
it('negate (jpeg)', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.negate()
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('negate.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('negate (png)', function(done) {
|
||||
sharp(fixtures.inputPng)
|
||||
.resize(320, 240)
|
||||
.negate()
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('png', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('negate.png'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('negate (png, trans)', function(done) {
|
||||
sharp(fixtures.inputPngWithTransparency)
|
||||
.resize(320, 240)
|
||||
.negate()
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('png', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('negate-trans.png'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('negate (png, alpha)', function(done) {
|
||||
sharp(fixtures.inputPngWithGreyAlpha)
|
||||
.resize(320, 240)
|
||||
.negate()
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('png', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('negate-alpha.png'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
if (sharp.format.webp.output.file) {
|
||||
it('negate (webp)', function(done) {
|
||||
sharp(fixtures.inputWebP)
|
||||
.resize(320, 240)
|
||||
.negate()
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('webp', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('negate.webp'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('negate (webp, trans)', function(done) {
|
||||
sharp(fixtures.inputWebPWithTransparency)
|
||||
.resize(320, 240)
|
||||
.negate()
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('webp', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('negate-trans.webp'), data, done);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it('negate (true)', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.negate(true)
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('negate.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('negate (false)', function(done) {
|
||||
var output = fixtures.path('output.unmodified-by-negate.png');
|
||||
sharp(fixtures.inputJpgWithLowContrast)
|
||||
.negate(false)
|
||||
.toFile(output, function(err, info) {
|
||||
if (err) done(err);
|
||||
fixtures.assertMaxColourDistance(output, fixtures.inputJpgWithLowContrast, 0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user