mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 18:40:16 +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)
|
#### background(rgba)
|
||||||
|
|
||||||
Set the background for the `embed`, `flatten` and `extend` operations.
|
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,
|
withMetadataOrientation: -1,
|
||||||
tileSize: 256,
|
tileSize: 256,
|
||||||
tileOverlap: 0,
|
tileOverlap: 0,
|
||||||
|
extractChannel: -1,
|
||||||
// Function to notify of queue length changes
|
// Function to notify of queue length changes
|
||||||
queueListener: function(queueLength) {
|
queueListener: function(queueLength) {
|
||||||
module.exports.queue.emit('change', queueLength);
|
module.exports.queue.emit('change', queueLength);
|
||||||
@ -303,6 +304,21 @@ Sharp.prototype.extract = function(options) {
|
|||||||
return this;
|
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.
|
Set the background colour for embed and flatten operations.
|
||||||
Delegates to the 'Color' module, which can throw an Error
|
Delegates to the 'Color' module, which can throw an Error
|
||||||
|
@ -789,6 +789,15 @@ class PipelineWorker : public AsyncWorker {
|
|||||||
image = Bandbool(image, baton->bandBoolOp);
|
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
|
// Override EXIF Orientation tag
|
||||||
if (baton->withMetadata && baton->withMetadataOrientation != -1) {
|
if (baton->withMetadata && baton->withMetadataOrientation != -1) {
|
||||||
SetExifOrientation(image, baton->withMetadataOrientation);
|
SetExifOrientation(image, baton->withMetadataOrientation);
|
||||||
@ -1175,6 +1184,7 @@ NAN_METHOD(pipeline) {
|
|||||||
baton->extendBottom = attrAs<int32_t>(options, "extendBottom");
|
baton->extendBottom = attrAs<int32_t>(options, "extendBottom");
|
||||||
baton->extendLeft = attrAs<int32_t>(options, "extendLeft");
|
baton->extendLeft = attrAs<int32_t>(options, "extendLeft");
|
||||||
baton->extendRight = attrAs<int32_t>(options, "extendRight");
|
baton->extendRight = attrAs<int32_t>(options, "extendRight");
|
||||||
|
baton->extractChannel = attrAs<int32_t>(options, "extractChannel");
|
||||||
// Output options
|
// Output options
|
||||||
baton->progressive = attrAs<bool>(options, "progressive");
|
baton->progressive = attrAs<bool>(options, "progressive");
|
||||||
baton->quality = attrAs<int32_t>(options, "quality");
|
baton->quality = attrAs<int32_t>(options, "quality");
|
||||||
|
@ -94,6 +94,7 @@ struct PipelineBaton {
|
|||||||
double convKernelScale;
|
double convKernelScale;
|
||||||
double convKernelOffset;
|
double convKernelOffset;
|
||||||
VipsOperationBoolean bandBoolOp;
|
VipsOperationBoolean bandBoolOp;
|
||||||
|
int extractChannel;
|
||||||
int tileSize;
|
int tileSize;
|
||||||
int tileOverlap;
|
int tileOverlap;
|
||||||
VipsForeignDzContainer tileContainer;
|
VipsForeignDzContainer tileContainer;
|
||||||
@ -155,6 +156,7 @@ struct PipelineBaton {
|
|||||||
convKernelScale(0.0),
|
convKernelScale(0.0),
|
||||||
convKernelOffset(0.0),
|
convKernelOffset(0.0),
|
||||||
bandBoolOp(VIPS_OPERATION_BOOLEAN_LAST),
|
bandBoolOp(VIPS_OPERATION_BOOLEAN_LAST),
|
||||||
|
extractChannel(-1),
|
||||||
tileSize(256),
|
tileSize(256),
|
||||||
tileOverlap(0),
|
tileOverlap(0),
|
||||||
tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
|
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