From c5efb77badc8f18786a4f4bcb6007b9697a99a64 Mon Sep 17 00:00:00 2001 From: Juliano Julio Costa Date: Fri, 22 Aug 2014 13:53:42 -0400 Subject: [PATCH] New withMetadata([boolean]) to keep metadata in the generated images. --- README.md | 7 ++++++- index.js | 6 ++++++ package.json | 3 ++- src/sharp.cc | 19 +++++++++++-------- tests/unit.js | 22 ++++++++++++++++++++++ 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 36e2c518..c231f3ec 100755 --- a/README.md +++ b/README.md @@ -130,12 +130,13 @@ sharp('input.png') .rotate(180) .resize(300) .sharpen() + .withMetadata() .quality(90) .webp() .toBuffer() .then(function(outputBuffer) { // outputBuffer contains 300px wide, upside down, sharpened, - // 90% quality WebP image data + // with metadata, 90% quality WebP image data }); ``` @@ -278,6 +279,10 @@ Possible interpolators, in order of performance, are: ### Output options +#### withMetadata([boolean]) + +Specifies if the output image should contains the original metadata or not. + #### progressive() Use progressive (interlace) scan for JPEG and PNG output. This typically reduces compression performance by 30% but results in an image that can be rendered sooner when decompressed. diff --git a/index.js b/index.js index 0281e08a..b6948027 100755 --- a/index.js +++ b/index.js @@ -26,6 +26,7 @@ var Sharp = function(input) { compressionLevel: 6, streamIn: false, streamOut: false, + withMetadata: false, output: '__input' }; if (typeof input === 'string') { @@ -190,6 +191,11 @@ Sharp.prototype.compressionLevel = function(compressionLevel) { return this; }; +Sharp.prototype.withMetadata = function(withMetadata) { + this.options.withMetadata = (typeof withMetadata === 'boolean') ? withMetadata : true; + return this; +}; + Sharp.prototype.resize = function(width, height) { if (!width) { this.options.width = -1; diff --git a/package.json b/package.json index 05b65fef..f2d21c5e 100755 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "contributors": [ "Pierre Inglebert ", "Jonathan Ong ", - "Chanon Sajjamanochai " + "Chanon Sajjamanochai ", + "Juliano Julio " ], "description": "High performance Node.js module to resize JPEG, PNG and WebP images using the libvips library", "scripts": { diff --git a/src/sharp.cc b/src/sharp.cc index 0024b0de..2c78854e 100755 --- a/src/sharp.cc +++ b/src/sharp.cc @@ -33,6 +33,7 @@ struct resize_baton { int compressionLevel; int angle; std::string err; + bool withMetadata; resize_baton(): buffer_in_len(0), @@ -42,7 +43,8 @@ struct resize_baton { max(false), sharpen(false), progressive(false), - without_enlargement(false) {} + without_enlargement(false), + withMetadata(false) {} }; typedef enum { @@ -585,37 +587,37 @@ class ResizeWorker : public NanAsyncWorker { VipsImage *output = cached; if (baton->output == "__jpeg" || (baton->output == "__input" && inputImageType == JPEG)) { // Write JPEG to buffer - if (vips_jpegsave_buffer(output, &baton->buffer_out, &baton->buffer_out_len, "strip", TRUE, "Q", baton->quality, "optimize_coding", TRUE, "interlace", baton->progressive, NULL)) { + if (vips_jpegsave_buffer(output, &baton->buffer_out, &baton->buffer_out_len, "strip", !baton->withMetadata, "Q", baton->quality, "optimize_coding", TRUE, "interlace", baton->progressive, NULL)) { return resize_error(baton, output); } } else if (baton->output == "__png" || (baton->output == "__input" && inputImageType == PNG)) { // Write PNG to buffer - if (vips_pngsave_buffer(output, &baton->buffer_out, &baton->buffer_out_len, "strip", TRUE, "compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) { + if (vips_pngsave_buffer(output, &baton->buffer_out, &baton->buffer_out_len, "strip", !baton->withMetadata, "compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) { return resize_error(baton, output); } } else if (baton->output == "__webp" || (baton->output == "__input" && inputImageType == WEBP)) { // Write WEBP to buffer - if (vips_webpsave_buffer(output, &baton->buffer_out, &baton->buffer_out_len, "strip", TRUE, "Q", baton->quality, NULL)) { + if (vips_webpsave_buffer(output, &baton->buffer_out, &baton->buffer_out_len, "strip", !baton->withMetadata, "Q", baton->quality, NULL)) { return resize_error(baton, output); } } else if (is_jpeg(baton->output)) { // Write JPEG to file - if (vips_jpegsave(output, baton->output.c_str(), "strip", TRUE, "Q", baton->quality, "optimize_coding", TRUE, "interlace", baton->progressive, NULL)) { + if (vips_jpegsave(output, baton->output.c_str(), "strip", !baton->withMetadata, "Q", baton->quality, "optimize_coding", TRUE, "interlace", baton->progressive, NULL)) { return resize_error(baton, output); } } else if (is_png(baton->output)) { // Write PNG to file - if (vips_pngsave(output, baton->output.c_str(), "strip", TRUE, "compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) { + if (vips_pngsave(output, baton->output.c_str(), "strip", !baton->withMetadata, "compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) { return resize_error(baton, output); } } else if (is_webp(baton->output)) { // Write WEBP to file - if (vips_webpsave(output, baton->output.c_str(), "strip", TRUE, "Q", baton->quality, NULL)) { + if (vips_webpsave(output, baton->output.c_str(), "strip", !baton->withMetadata, "Q", baton->quality, NULL)) { return resize_error(baton, output); } } else if (is_tiff(baton->output)) { // Write TIFF to file - if (vips_tiffsave(output, baton->output.c_str(), "strip", TRUE, "compression", VIPS_FOREIGN_TIFF_COMPRESSION_JPEG, "Q", baton->quality, NULL)) { + if (vips_tiffsave(output, baton->output.c_str(), "strip", !baton->withMetadata, "compression", VIPS_FOREIGN_TIFF_COMPRESSION_JPEG, "Q", baton->quality, NULL)) { return resize_error(baton, output); } } else { @@ -706,6 +708,7 @@ NAN_METHOD(resize) { baton->quality = options->Get(NanNew("quality"))->Int32Value(); baton->compressionLevel = options->Get(NanNew("compressionLevel"))->Int32Value(); baton->angle = options->Get(NanNew("angle"))->Int32Value(); + baton->withMetadata = options->Get(NanNew("withMetadata"))->BooleanValue(); // Output filename or __format for Buffer baton->output = *String::Utf8Value(options->Get(NanNew("output"))->ToString()); diff --git a/tests/unit.js b/tests/unit.js index ba9a79a8..31d14cc9 100755 --- a/tests/unit.js +++ b/tests/unit.js @@ -422,6 +422,28 @@ async.series([ done(); }); }, + // Keeps Metadata after a resize + function(done) { + sharp(inputJpgWithExif).resize(320, 240).withMetadata().toBuffer(function(err, buffer) { + if (err) throw err; + sharp(buffer).metadata(function(err, metadata) { + if (err) throw err; + assert.strictEqual(8, metadata.orientation); + done(); + }); + }); + }, + // Keeps Metadata after a resize + function(done) { + sharp(inputJpgWithExif).resize(320, 240).withMetadata(false).toBuffer(function(err, buffer) { + if (err) throw err; + sharp(buffer).metadata(function(err, metadata) { + if (err) throw err; + assert.strictEqual('undefined', typeof metadata.orientation); + done(); + }); + }); + }, // Metadata - JPEG function(done) { sharp(inputJpg).metadata(function(err, metadata) {