From f99e42d447c670c664df149d0c4182bd993da979 Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Mon, 3 Mar 2014 23:24:09 +0000 Subject: [PATCH] Add support for auto-scaling of width and height --- README.md | 14 +++++++------- index.js | 9 +++++++-- package.json | 4 ++-- src/sharp.cc | 23 ++++++++++++++++++++--- tests/random.js | 2 +- tests/unit.js | 34 ++++++++++++++++++++++++++++++++++ 6 files changed, 71 insertions(+), 15 deletions(-) create mode 100755 tests/unit.js diff --git a/README.md b/README.md index f4fb9f3a..8e9c6b1d 100755 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Under the hood you'll find the blazingly fast [libvips](https://github.com/jcupi git clone https://github.com/jcupitt/libvips.git cd libvips ./bootstrap.sh - ./configure --enable-debug=no --enable-cxx=no --without-magick --without-lcms --without-OpenEXR --without-openslide --without-matio --without-cfitsio --without-pangoft2 --without-zip --without-libexif --without-python + ./configure --enable-debug=no make sudo make install sudo ldconfig @@ -52,9 +52,9 @@ Scale and crop to `width` x `height` calling `callback` when complete. `output` can either be a filename String or one of `sharp.buffer.jpeg`, `sharp.buffer.png` or `sharp.buffer.webp` to pass a Buffer containing JPEG, PNG or WebP image data to `callback`. -`width` is the Number of pixels wide the resultant image should be. +`width` is the Number of pixels wide the resultant image should be. Use a value of -1 to auto-scale the width to match the height. -`height` is the Number of pixels high the resultant image should be. +`height` is the Number of pixels high the resultant image should be. Use a value of -1 to auto-scale the height to match the width. `options` is optional, and can contain one or more of: @@ -78,20 +78,20 @@ sharp.resize("input.jpg", "output.jpg", 300, 200, function(err) { ``` ```javascript -sharp.resize("input.jpg", sharp.buffer.jpeg, 300, 200, {progressive: true}, function(err, buffer) { +sharp.resize("input.jpg", sharp.buffer.jpeg, -1, 200, {progressive: true}, function(err, buffer) { if (err) { throw err; } - // buffer contains progressive JPEG image data + // buffer contains progressive JPEG image data, 200 pixels high }); ``` ```javascript -sharp.resize("input.webp", sharp.buffer.png, 300, 200, {sharpen: true}, function(err, buffer) { +sharp.resize("input.webp", sharp.buffer.png, 300, -1, {sharpen: true}, function(err, buffer) { if (err) { throw err; } - // buffer contains sharpened PNG image data (converted from JPEG) + // buffer contains sharpened PNG image data (converted from JPEG), 300 pixels wide }); ``` diff --git a/index.js b/index.js index c69c5745..fa8ab09d 100755 --- a/index.js +++ b/index.js @@ -42,6 +42,10 @@ module.exports.resize = function(input, output, width, height, options, callback callback("Invalid height " + height); return; } + if (outWidth < 1 && outHeight < 1) { + callback("Width and/or height required"); + return; + } var canvas = options.canvas || "c"; if (canvas.length !== 1 || "cwb".indexOf(canvas) === -1) { callback("Invalid canvas " + canvas); @@ -50,15 +54,16 @@ module.exports.resize = function(input, output, width, height, options, callback var sharpen = !!options.sharpen; var progessive = !!options.progessive; var sequentialRead = !!options.sequentialRead; - sharp.resize(options.inFile, options.inBuffer, output, width, height, canvas, sharpen, progessive, sequentialRead, callback); + sharp.resize(options.inFile, options.inBuffer, output, outWidth, outHeight, canvas, sharpen, progessive, sequentialRead, callback); }; module.exports.cache = function(limit) { + "use strict"; if (Number.isNaN(limit)) { limit = null; } return sharp.cache(limit); -} +}; /* Deprecated v0.0.x methods */ module.exports.crop = function(input, output, width, height, sharpen, callback) { diff --git a/package.json b/package.json index dccf9177..67b5beab 100755 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "sharp", - "version": "0.1.7", + "version": "0.1.8", "author": "Lovell Fuller", "description": "High performance module to resize JPEG, PNG, WebP and TIFF images using the libvips image processing library", "scripts": { - "test": "node tests/perf.js" + "test": "node tests/unit && node tests/perf" }, "main": "index.js", "repository": { diff --git a/src/sharp.cc b/src/sharp.cc index f79701d2..67110015 100755 --- a/src/sharp.cc +++ b/src/sharp.cc @@ -15,8 +15,8 @@ struct resize_baton { std::string file_out; void* buffer_out; size_t buffer_out_len; - int width; - int height; + int width; + int height; bool crop; VipsExtend extend; bool sharpen; @@ -119,7 +119,24 @@ void resize_async(uv_work_t *work) { double xfactor = static_cast(in->Xsize) / std::max(baton->width, 1); double yfactor = static_cast(in->Ysize) / std::max(baton->height, 1); - double factor = baton->crop ? std::min(xfactor, yfactor) : std::max(xfactor, yfactor); + double factor; + if (baton->width > 0 && baton->height > 0) { + // Fixed width and height + factor = baton->crop ? std::min(xfactor, yfactor) : std::max(xfactor, yfactor); + } else if (baton->width > 0) { + // Fixed width, auto height + factor = xfactor; + baton->height = floor(in->Ysize * factor); + } else if (baton->height > 0) { + // Fixed height, auto width + factor = yfactor; + baton->width = floor(in->Xsize * factor); + } else { + resize_error(baton, in); + (baton->err).append("Width and/or height required"); + return; + } + factor = std::max(factor, 1.0); int shrink = floor(factor); double residual = shrink / factor; diff --git a/tests/random.js b/tests/random.js index 7c550975..f3e5b9ac 100755 --- a/tests/random.js +++ b/tests/random.js @@ -15,7 +15,7 @@ var max = 960; var randomDimension = function() { return Math.random() * (max - min) + min; -} +}; new Benchmark.Suite("random").add("imagemagick", { defer: true, diff --git a/tests/unit.js b/tests/unit.js new file mode 100755 index 00000000..3a9b82e9 --- /dev/null +++ b/tests/unit.js @@ -0,0 +1,34 @@ +var sharp = require("../index"); +var imagemagick = require("imagemagick"); +var assert = require("assert"); + +var inputJpg = __dirname + "/2569067123_aca715a2ee_o.jpg"; // http://www.flickr.com/photos/grizdave/2569067123/ +var outputJpg = __dirname + "/output.jpg"; + +sharp.resize(inputJpg, outputJpg, 320, 240, function(err) { + if (err) throw err; + imagemagick.identify(outputJpg, function(err, features) { + if (err) throw err; + assert.strictEqual(320, features.width); + assert.strictEqual(240, features.height); + + sharp.resize(inputJpg, outputJpg, 320, -1, function(err) { + if (err) throw err; + imagemagick.identify(outputJpg, function(err, features) { + if (err) throw err; + assert.strictEqual(320, features.width); + assert.strictEqual(262, features.height); + }); + + sharp.resize(inputJpg, outputJpg, -1, 320, function(err) { + if (err) throw err; + imagemagick.identify(outputJpg, function(err, features) { + if (err) throw err; + assert.strictEqual(392, features.width); + assert.strictEqual(320, features.height); + }); + }); + + }); + }); +});