From 276ba5228b56945be6ff5af169d8793b5ffa680b Mon Sep 17 00:00:00 2001 From: Lovell Fuller Date: Mon, 19 May 2014 21:52:47 +0100 Subject: [PATCH] Add usage example and further unit test for new max option Simplify max vs crop logic --- README.md | 26 +++++++++++++++++++------- src/sharp.cc | 16 +++++++--------- tests/unit.js | 16 ++++++++++++++-- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 9d04c063..ee89b9d2 100755 --- a/README.md +++ b/README.md @@ -85,25 +85,25 @@ sharp('input.jpg').resize(300, 200).write('output.jpg', function(err) { ``` ```javascript -sharp('input.jpg').resize(null, 200).progressive().toBuffer(function(err, buffer) { +sharp('input.jpg').resize(null, 200).progressive().toBuffer(function(err, outputBuffer) { if (err) { throw err; } - // buffer contains progressive JPEG image data, 200 pixels high + // outputBuffer contains progressive JPEG image data, 200 pixels high }); ``` ```javascript -sharp('input.png').resize(300).sharpen().quality(90).webp(function(err, buffer) { +sharp('input.png').resize(300).sharpen().quality(90).webp(function(err, outputBuffer) { if (err) { throw err; } - // buffer contains 300 pixels wide, sharpened, 90% quality WebP image data + // outputBuffer contains 300 pixels wide, sharpened, 90% quality WebP image data }); ``` ```javascript -sharp(buffer).resize(200, 300).embedWhite().write('output.tiff', function(err) { +sharp(inputBuffer).resize(200, 300).embedWhite().write('output.tiff', function(err) { if (err) { throw err; } @@ -113,15 +113,25 @@ sharp(buffer).resize(200, 300).embedWhite().write('output.tiff', function(err) { ``` ```javascript -sharp('input.gif').resize(200, 300).embedBlack().webp(function(err, buffer) { +sharp('input.gif').resize(200, 300).embedBlack().webp(function(err, outputBuffer) { if (err) { throw err; } - // buffer contains WebP image data of a 200 pixels wide and 300 pixels high image + // outputBuffer contains WebP image data of a 200 pixels wide and 300 pixels high // containing a scaled version, embedded on a black canvas, of input.gif }); ``` +```javascript +sharp(inputBuffer).resize(200, 200).max().jpeg(function(err, outputBuffer) { + if (err) { + throw err; + } + // outputBuffer contains JPEG image data no wider than 200 pixels and no higher + // than 200 pixels regardless of the inputBuffer image dimensions +}); +``` + ## API ### sharp(input) @@ -147,6 +157,8 @@ Crop the resized image to the exact size specified, the default behaviour. Preserving aspect ratio, resize the image to the maximum width or height specified. +Both `width` and `height` must be provided via `resize` otherwise the behaviour will default to `crop`. + ### embedWhite() Embed the resized image on a white background of the exact size specified. diff --git a/src/sharp.cc b/src/sharp.cc index 3ae31164..d2973aa5 100755 --- a/src/sharp.cc +++ b/src/sharp.cc @@ -140,11 +140,11 @@ class ResizeWorker : public NanAsyncWorker { double yfactor = static_cast(in->Ysize) / static_cast(baton->height); factor = baton->crop ? std::min(xfactor, yfactor) : std::max(xfactor, yfactor); // if max is set, we need to compute the real size of the thumb image - if(baton->max) { - if(xfactor > yfactor) { - baton->height = round(in->Ysize/factor); + if (baton->max) { + if (xfactor > yfactor) { + baton->height = round(static_cast(in->Ysize) / xfactor); } else { - baton->width = round(in->Xsize/factor); + baton->width = round(static_cast(in->Xsize) / yfactor); } } } else if (baton->width > 0) { @@ -235,8 +235,8 @@ class ResizeWorker : public NanAsyncWorker { // Crop/embed VipsImage *canvased = vips_image_new(); if (affined->Xsize != baton->width || affined->Ysize != baton->height) { - if (baton->crop || baton->max) { - // Crop + if (baton->crop) { + // Crop/max int width = std::min(affined->Xsize, baton->width); int height = std::min(affined->Ysize, baton->height); int left = (affined->Xsize - width + 1) / 2; @@ -355,13 +355,11 @@ NAN_METHOD(resize) { if (canvas->Equals(NanSymbol("c"))) { baton->crop = true; } else if (canvas->Equals(NanSymbol("w"))) { - baton->crop = false; baton->extend = VIPS_EXTEND_WHITE; } else if (canvas->Equals(NanSymbol("b"))) { - baton->crop = false; baton->extend = VIPS_EXTEND_BLACK; } else if (canvas->Equals(NanSymbol("m"))) { - baton->crop = false; + baton->crop = true; baton->max = true; } baton->sharpen = args[6]->BooleanValue(); diff --git a/tests/unit.js b/tests/unit.js index 2697cc21..bdb8d574 100755 --- a/tests/unit.js +++ b/tests/unit.js @@ -112,7 +112,7 @@ async.series([ }, // Resize to max width or height considering ratio (landscape) function(done) { - sharp(inputJpg).resize(320,320).max().write(outputJpg, function(err) { + sharp(inputJpg).resize(320, 320).max().write(outputJpg, function(err) { if (err) throw err; imagemagick.identify(outputJpg, function(err, features) { if (err) throw err; @@ -124,7 +124,7 @@ async.series([ }, // Resize to max width or height considering ratio (portrait) function(done) { - sharp(inputTiff).resize(320,320).max().write(outputJpg, function(err) { + sharp(inputTiff).resize(320, 320).max().write(outputJpg, function(err) { if (err) throw err; imagemagick.identify(outputJpg, function(err, features) { if (err) throw err; @@ -133,5 +133,17 @@ async.series([ done(); }); }); + }, + // Attempt to resize to max but only provide one dimension, so should default to crop + function(done) { + sharp(inputJpg).resize(320).max().write(outputJpg, function(err) { + if (err) throw err; + imagemagick.identify(outputJpg, function(err, features) { + if (err) throw err; + assert.strictEqual(320, features.width); + assert.strictEqual(261, features.height); + done(); + }); + }); } ]);