Improved performance benchmarks and usage docs

This commit is contained in:
Lovell Fuller 2013-08-26 16:10:48 +01:00
parent 9ba9b95648
commit b836704451
3 changed files with 82 additions and 46 deletions

View File

@ -11,7 +11,9 @@ The typical use case for this high performance Node.js module is to convert a la
It is somewhat opinionated in that it only deals with JPEG images, always obeys the requested dimensions by either cropping or embedding and insists on a mild sharpen of the resulting image. It is somewhat opinionated in that it only deals with JPEG images, always obeys the requested dimensions by either cropping or embedding and insists on a mild sharpen of the resulting image.
Under the hood you'll find the blazingly fast [libvips](https://github.com/jcupitt/libvips) image processing library, originally created in 1989 at Birkbeck College and currently maintained by the University of Southampton. Speed is typically 25-30% faster than the imagemagick equivalent. Under the hood you'll find the blazingly fast [libvips](https://github.com/jcupitt/libvips) image processing library, originally created in 1989 at Birkbeck College and currently maintained by the University of Southampton.
Speed is typically 4x faster than the imagemagick equivalent.
## Prerequisites ## Prerequisites
@ -26,7 +28,7 @@ Ubuntu 12.04 LTS:
sudo ln -s /usr/lib/pkgconfig/vips-7.26.pc /usr/lib/pkgconfig/vips.pc sudo ln -s /usr/lib/pkgconfig/vips-7.26.pc /usr/lib/pkgconfig/vips.pc
Ubuntu 13.04: Ubuntu 13.04 (64-bit):
sudo ln -s /usr/lib/x86_64-linux-gnu/pkgconfig/vips-7.28.pc /usr/lib/pkgconfig/vips.pc sudo ln -s /usr/lib/x86_64-linux-gnu/pkgconfig/vips-7.28.pc /usr/lib/pkgconfig/vips.pc
@ -36,28 +38,59 @@ Ubuntu 13.04:
## Usage ## Usage
var sharp = require("sharp");
### crop(inputPath, outputPath, width, height, callback)
Scale and crop JPEG `inputPath` to `width` x `height` and write JPEG to `outputPath` calling `callback` when complete.
Example:
```javascript ```javascript
var sharp = require("sharp");
sharp.crop("input.jpg", "output.jpg", 300, 200, function(err) { sharp.crop("input.jpg", "output.jpg", 300, 200, function(err) {
if (err) { if (err) {
throw err; throw err;
} }
// output.jpg is cropped input.jpg // output.jpg is a 300 pixels wide and 200 pixels high image
// containing a scaled and cropped version of input.jpg
}); });
```
### embedWhite(inputPath, outputPath, width, height, callback)
Scale and embed JPEG `inputPath` to `width` x `height` using a white canvas and write JPEG to `outputPath` calling `callback` when complete.
```javascript
sharp.embedWhite("input.jpg", "output.jpg", 200, 300, function(err) { sharp.embedWhite("input.jpg", "output.jpg", 200, 300, function(err) {
if (err) { if (err) {
throw err; throw err;
} }
// output.jpg contains input.jpg embedded with a white border // output.jpg is a 300 pixels wide and 200 pixels high image
// containing a scaled version of input.jpg embedded on a white canvas
}); });
```
### embedBlack(inputPath, outputPath, width, height, callback)
Scale and embed JPEG `inputPath` to `width` x `height` using a black canvas and write JPEG to `outputPath` calling `callback` when complete.
```javascript
sharp.embedBlack("input.jpg", "output.jpg", 200, 300, function(err) { sharp.embedBlack("input.jpg", "output.jpg", 200, 300, function(err) {
if (err) { if (err) {
throw err; throw err;
} }
// output.jpg contains input.jpg embedded with a black border // output.jpg is a 300 pixels wide and 200 pixels high image
// containing a scaled version of input.jpg embedded on a black canvas
}); });
``` ```
## Testing [![Build Status](https://travis-ci.org/lovell/sharp.png?branch=master)](https://travis-ci.org/lovell/sharp) ## Testing [![Build Status](https://travis-ci.org/lovell/sharp.png?branch=master)](https://travis-ci.org/lovell/sharp)
npm test npm test
## Performance
Using an AMD Athlon quad core CPU with 512KB L2 cache clocked at 3.3GHz with 8GB RAM:
* imagemagick x 5.55 ops/sec ±0.68% (31 runs sampled)
* sharp x 24.49 ops/sec ±6.85% (64 runs sampled)

View File

@ -1,14 +1,15 @@
{ {
"name": "sharp", "name": "sharp",
"version": "0.0.1", "version": "0.0.2",
"main": "./build/Release/sharp", "main": "index.js",
"description": "High performance Node.js module to resize JPEG images using the libvips image processing library", "description": "High performance Node.js module to resize JPEG images using the libvips image processing library",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/lovell/sharp" "url": "git://github.com/lovell/sharp"
}, },
"devDependencies": { "devDependencies": {
"imagemagick": "*" "imagemagick": "*",
"benchmark": "*"
}, },
"scripts": { "scripts": {
"test": "node tests/perf.js" "test": "node tests/perf.js"

View File

@ -1,42 +1,44 @@
var sharp = require("../index"); var sharp = require("../index");
var imagemagick = require("imagemagick"); var imagemagick = require("imagemagick");
var assert = require("assert"); var assert = require("assert");
var Benchmark = require("benchmark");
// http://www.flickr.com/photos/grizdave/2569067123/ var input = __dirname + "/2569067123_aca715a2ee_o.jpg"; // http://www.flickr.com/photos/grizdave/2569067123/
var input = __dirname + "/2569067123_aca715a2ee_o.jpg";
var output = __dirname + "/output.jpg"; var output = __dirname + "/output.jpg";
var width = 640; var width = 640;
var height = 480; var height = 480;
// imagemagick var suite = new Benchmark.Suite;
var time = process.hrtime(); suite.add("imagemagick", {
imagemagick.resize({ "defer": true,
"fn": function(deferred) {
imagemagick.resize({
srcPath: input, srcPath: input,
dstPath: output, dstPath: output,
quality: 0.75, quality: 0.75,
width: width, width: width,
height: height height: height
}, function(err) { }, function(err) {
if (err) { if (err) {
throw err; throw err;
} else {
deferred.resolve();
} }
var diff = process.hrtime(time); });
imagemagickTime = diff[0] * 1e9 + diff[1]; }
console.log("imagemagick took %d nanoseconds", imagemagickTime); }).add("sharp", {
"defer": true,
// sharp "fn": function(deferred) {
time = process.hrtime();
sharp.crop(input, output, width, height, function(err) { sharp.crop(input, output, width, height, function(err) {
if (err) { if (err) {
throw err; throw err;
} else {
deferred.resolve();
} }
diff = process.hrtime(time);
var sharpTime = diff[0] * 1e9 + diff[1];
console.log("sharp took %d nanoseconds", sharpTime);
// diff
assert(sharpTime < imagemagickTime, "sharp was blunt");
console.log("sharp was %d%% faster", (imagemagickTime - sharpTime) / imagemagickTime * 100);
}); });
}); }
}).on("cycle", function(event) {
console.log(String(event.target));
}).on("complete", function() {
assert(this.filter("fastest").pluck("name") == "sharp");
}).run();