Add support for auto-scaling of width and height

This commit is contained in:
Lovell Fuller 2014-03-03 23:24:09 +00:00
parent 9b4387be97
commit f99e42d447
6 changed files with 71 additions and 15 deletions

View File

@ -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 git clone https://github.com/jcupitt/libvips.git
cd libvips cd libvips
./bootstrap.sh ./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 make
sudo make install sudo make install
sudo ldconfig 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`. `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: `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 ```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) { if (err) {
throw err; throw err;
} }
// buffer contains progressive JPEG image data // buffer contains progressive JPEG image data, 200 pixels high
}); });
``` ```
```javascript ```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) { if (err) {
throw err; throw err;
} }
// buffer contains sharpened PNG image data (converted from JPEG) // buffer contains sharpened PNG image data (converted from JPEG), 300 pixels wide
}); });
``` ```

View File

@ -42,6 +42,10 @@ module.exports.resize = function(input, output, width, height, options, callback
callback("Invalid height " + height); callback("Invalid height " + height);
return; return;
} }
if (outWidth < 1 && outHeight < 1) {
callback("Width and/or height required");
return;
}
var canvas = options.canvas || "c"; var canvas = options.canvas || "c";
if (canvas.length !== 1 || "cwb".indexOf(canvas) === -1) { if (canvas.length !== 1 || "cwb".indexOf(canvas) === -1) {
callback("Invalid canvas " + canvas); callback("Invalid canvas " + canvas);
@ -50,15 +54,16 @@ module.exports.resize = function(input, output, width, height, options, callback
var sharpen = !!options.sharpen; var sharpen = !!options.sharpen;
var progessive = !!options.progessive; var progessive = !!options.progessive;
var sequentialRead = !!options.sequentialRead; 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) { module.exports.cache = function(limit) {
"use strict";
if (Number.isNaN(limit)) { if (Number.isNaN(limit)) {
limit = null; limit = null;
} }
return sharp.cache(limit); return sharp.cache(limit);
} };
/* Deprecated v0.0.x methods */ /* Deprecated v0.0.x methods */
module.exports.crop = function(input, output, width, height, sharpen, callback) { module.exports.crop = function(input, output, width, height, sharpen, callback) {

View File

@ -1,10 +1,10 @@
{ {
"name": "sharp", "name": "sharp",
"version": "0.1.7", "version": "0.1.8",
"author": "Lovell Fuller", "author": "Lovell Fuller",
"description": "High performance module to resize JPEG, PNG, WebP and TIFF images using the libvips image processing library", "description": "High performance module to resize JPEG, PNG, WebP and TIFF images using the libvips image processing library",
"scripts": { "scripts": {
"test": "node tests/perf.js" "test": "node tests/unit && node tests/perf"
}, },
"main": "index.js", "main": "index.js",
"repository": { "repository": {

View File

@ -119,7 +119,24 @@ void resize_async(uv_work_t *work) {
double xfactor = static_cast<double>(in->Xsize) / std::max(baton->width, 1); double xfactor = static_cast<double>(in->Xsize) / std::max(baton->width, 1);
double yfactor = static_cast<double>(in->Ysize) / std::max(baton->height, 1); double yfactor = static_cast<double>(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); factor = std::max(factor, 1.0);
int shrink = floor(factor); int shrink = floor(factor);
double residual = shrink / factor; double residual = shrink / factor;

View File

@ -15,7 +15,7 @@ var max = 960;
var randomDimension = function() { var randomDimension = function() {
return Math.random() * (max - min) + min; return Math.random() * (max - min) + min;
} };
new Benchmark.Suite("random").add("imagemagick", { new Benchmark.Suite("random").add("imagemagick", {
defer: true, defer: true,

34
tests/unit.js Executable file
View File

@ -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);
});
});
});
});
});