mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Add extractChannel operation to extract a channel from an image (#497)
This commit is contained in:
parent
f672f86b53
commit
83d8847f57
19
docs/api.md
19
docs/api.md
@ -298,6 +298,25 @@ sharp(input)
|
||||
});
|
||||
```
|
||||
|
||||
#### extractChannel(channel)
|
||||
|
||||
Extract a channel from the image. The following channel names are equivalent:
|
||||
|
||||
* Red: `0, 'red'`
|
||||
* Green: `1, 'green'`
|
||||
* Blue: `2, 'blue'`
|
||||
|
||||
The result will be a single-channel grayscale image.
|
||||
|
||||
```javascript
|
||||
sharp(input)
|
||||
.extractChannel('green')
|
||||
.toFile('input_green.jpg',function(err, info) {
|
||||
// info.channels === 1
|
||||
// input_green.jpg contains the green channel of the input image
|
||||
});
|
||||
```
|
||||
|
||||
#### background(rgba)
|
||||
|
||||
Set the background for the `embed`, `flatten` and `extend` operations.
|
||||
|
16
index.js
16
index.js
@ -115,6 +115,7 @@ var Sharp = function(input, options) {
|
||||
withMetadataOrientation: -1,
|
||||
tileSize: 256,
|
||||
tileOverlap: 0,
|
||||
extractChannel: -1,
|
||||
// Function to notify of queue length changes
|
||||
queueListener: function(queueLength) {
|
||||
module.exports.queue.emit('change', queueLength);
|
||||
@ -303,6 +304,21 @@ Sharp.prototype.extract = function(options) {
|
||||
return this;
|
||||
};
|
||||
|
||||
Sharp.prototype.extractChannel = function(channel) {
|
||||
if (channel === 'red')
|
||||
channel = 0;
|
||||
else if (channel === 'green')
|
||||
channel = 1;
|
||||
else if (channel === 'blue')
|
||||
channel = 2;
|
||||
if(isInteger(channel) && inRange(channel,0,4)) {
|
||||
this.options.extractChannel = channel;
|
||||
} else {
|
||||
throw new Error('Cannot extract invalid channel ' + channel);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/*
|
||||
Set the background colour for embed and flatten operations.
|
||||
Delegates to the 'Color' module, which can throw an Error
|
||||
|
@ -789,6 +789,15 @@ class PipelineWorker : public AsyncWorker {
|
||||
image = Bandbool(image, baton->bandBoolOp);
|
||||
}
|
||||
|
||||
// Extract an image channel (aka vips band)
|
||||
if(baton->extractChannel > -1) {
|
||||
if(baton->extractChannel >= image.bands()) {
|
||||
(baton->err).append("Cannot extract channel from image. Too few channels in image.");
|
||||
return Error();
|
||||
}
|
||||
image = image.extract_band(baton->extractChannel);
|
||||
}
|
||||
|
||||
// Override EXIF Orientation tag
|
||||
if (baton->withMetadata && baton->withMetadataOrientation != -1) {
|
||||
SetExifOrientation(image, baton->withMetadataOrientation);
|
||||
@ -1175,6 +1184,7 @@ NAN_METHOD(pipeline) {
|
||||
baton->extendBottom = attrAs<int32_t>(options, "extendBottom");
|
||||
baton->extendLeft = attrAs<int32_t>(options, "extendLeft");
|
||||
baton->extendRight = attrAs<int32_t>(options, "extendRight");
|
||||
baton->extractChannel = attrAs<int32_t>(options, "extractChannel");
|
||||
// Output options
|
||||
baton->progressive = attrAs<bool>(options, "progressive");
|
||||
baton->quality = attrAs<int32_t>(options, "quality");
|
||||
|
@ -94,6 +94,7 @@ struct PipelineBaton {
|
||||
double convKernelScale;
|
||||
double convKernelOffset;
|
||||
VipsOperationBoolean bandBoolOp;
|
||||
int extractChannel;
|
||||
int tileSize;
|
||||
int tileOverlap;
|
||||
VipsForeignDzContainer tileContainer;
|
||||
@ -155,6 +156,7 @@ struct PipelineBaton {
|
||||
convKernelScale(0.0),
|
||||
convKernelOffset(0.0),
|
||||
bandBoolOp(VIPS_OPERATION_BOOLEAN_LAST),
|
||||
extractChannel(-1),
|
||||
tileSize(256),
|
||||
tileOverlap(0),
|
||||
tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
|
||||
|
BIN
test/fixtures/expected/extract-blue.jpg
vendored
Normal file
BIN
test/fixtures/expected/extract-blue.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
test/fixtures/expected/extract-green.jpg
vendored
Normal file
BIN
test/fixtures/expected/extract-green.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
test/fixtures/expected/extract-red.jpg
vendored
Normal file
BIN
test/fixtures/expected/extract-red.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
72
test/unit/extractChannel.js
Normal file
72
test/unit/extractChannel.js
Normal file
@ -0,0 +1,72 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
|
||||
var sharp = require('../../index');
|
||||
var fixtures = require('../fixtures');
|
||||
|
||||
describe('Image channel extraction', function() {
|
||||
|
||||
it('Red channel', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.extractChannel('red')
|
||||
.resize(320,240)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('extract-red.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('Green channel', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.extractChannel('green')
|
||||
.resize(320,240)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('extract-green.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('Blue channel', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.extractChannel('blue')
|
||||
.resize(320,240)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('extract-blue.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('Blue channel by number', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.extractChannel(2)
|
||||
.resize(320,240)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('extract-blue.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('Invalid channel number', function() {
|
||||
assert.throws(function() {
|
||||
sharp(fixtures.inputJpg)
|
||||
.extractChannel(-1);
|
||||
});
|
||||
});
|
||||
|
||||
it('No arguments', function() {
|
||||
assert.throws(function() {
|
||||
sharp(fixtures.inputJpg)
|
||||
.extractChannel();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user