Skip to content

Commit 01b4d6e

Browse files
committed
Add highly-experimental 'clone' method
Cloned instances share a common input Very useful for Stream-based input
1 parent 1091be3 commit 01b4d6e

File tree

3 files changed

+65
-1
lines changed

3 files changed

+65
-1
lines changed

index.js

+18
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,24 @@ Sharp.prototype.metadata = function(callback) {
760760
}
761761
};
762762

763+
/*
764+
Clone new instance using existing options.
765+
Cloned instances share the same input.
766+
*/
767+
Sharp.prototype.clone = function() {
768+
// Clone existing options
769+
var clone = new Sharp();
770+
util._extend(clone.options, this.options);
771+
clone.streamIn = false;
772+
// Pass 'finish' event to clone for Stream-based input
773+
this.on('finish', function() {
774+
// Clone inherits input data
775+
clone.options.bufferIn = this.options.bufferIn;
776+
clone.emit('finish');
777+
});
778+
return clone;
779+
};
780+
763781
/*
764782
Get and set cache memory and item limits
765783
*/

src/pipeline.cc

-1
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,6 @@ NAN_METHOD(pipeline) {
12221222
baton->bufferInLength = node::Buffer::Length(buffer);
12231223
baton->bufferIn = new char[baton->bufferInLength];
12241224
memcpy(baton->bufferIn, node::Buffer::Data(buffer), baton->bufferInLength);
1225-
options->Set(NanNew<String>("bufferIn"), NanNull());
12261225
}
12271226
// ICC profile to use when input CMYK image has no embedded profile
12281227
baton->iccProfilePath = *String::Utf8Value(options->Get(NanNew<String>("iccProfilePath"))->ToString());

test/unit/io.js

+47
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,53 @@ describe('Input/output', function() {
106106
readable.pipe(pipeline).pipe(writable);
107107
});
108108

109+
it('Read from Stream and write to multiple Streams', function(done) {
110+
var finishEventsExpected = 2;
111+
// Output stream 1
112+
var output1 = fixtures.path('output.multi-stream.1.jpg');
113+
var writable1 = fs.createWriteStream(output1);
114+
writable1.on('finish', function() {
115+
sharp(output1).toBuffer(function(err, data, info) {
116+
if (err) throw err;
117+
assert.strictEqual(true, data.length > 0);
118+
assert.strictEqual(data.length, info.size);
119+
assert.strictEqual('jpeg', info.format);
120+
assert.strictEqual(320, info.width);
121+
assert.strictEqual(240, info.height);
122+
fs.unlinkSync(output1);
123+
finishEventsExpected--;
124+
if (finishEventsExpected === 0) {
125+
done();
126+
}
127+
});
128+
});
129+
// Output stream 2
130+
var output2 = fixtures.path('output.multi-stream.2.jpg');
131+
var writable2 = fs.createWriteStream(output2);
132+
writable2.on('finish', function() {
133+
sharp(output2).toBuffer(function(err, data, info) {
134+
if (err) throw err;
135+
assert.strictEqual(true, data.length > 0);
136+
assert.strictEqual(data.length, info.size);
137+
assert.strictEqual('jpeg', info.format);
138+
assert.strictEqual(100, info.width);
139+
assert.strictEqual(122, info.height);
140+
fs.unlinkSync(output2);
141+
finishEventsExpected--;
142+
if (finishEventsExpected === 0) {
143+
done();
144+
}
145+
});
146+
});
147+
// Create parent instance
148+
var rotator = sharp().rotate(90);
149+
// Cloned instances with differing dimensions
150+
rotator.clone().resize(320, 240).pipe(writable1);
151+
rotator.clone().resize(100).pipe(writable2);
152+
// Go
153+
fs.createReadStream(fixtures.inputJpg).pipe(rotator);
154+
});
155+
109156
it('Handle Stream to Stream error ', function(done) {
110157
var pipeline = sharp().resize(320, 240);
111158
var anErrorWasEmitted = false;

0 commit comments

Comments
 (0)