+8
-7
| { | ||
| "name": "sharp", | ||
| "version": "0.0.1", | ||
| "main": "./build/Release/sharp", | ||
| "version": "0.0.2", | ||
| "main": "index.js", | ||
| "description": "High performance Node.js module to resize JPEG images using the libvips image processing library", | ||
@@ -11,3 +11,4 @@ "repository": { | ||
| "devDependencies": { | ||
| "imagemagick": "*" | ||
| "imagemagick": "*", | ||
| "benchmark": "*" | ||
| }, | ||
@@ -24,7 +25,7 @@ "scripts": { | ||
| "thumbnail", | ||
| "sharpen", | ||
| "crop", | ||
| "embed", | ||
| "sharpen", | ||
| "crop", | ||
| "embed", | ||
| "libvips", | ||
| "fast" | ||
| "fast" | ||
| ], | ||
@@ -31,0 +32,0 @@ "author": "Lovell Fuller", |
+39
-6
@@ -14,4 +14,6 @@ # sharp | ||
| 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 | ||
@@ -30,3 +32,3 @@ | ||
| Ubuntu 13.04: | ||
| Ubuntu 13.04 (64-bit): | ||
@@ -41,4 +43,11 @@ sudo ln -s /usr/lib/x86_64-linux-gnu/pkgconfig/vips-7.28.pc /usr/lib/pkgconfig/vips.pc | ||
| 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 | ||
| var sharp = require("sharp"); | ||
| sharp.crop("input.jpg", "output.jpg", 300, 200, function(err) { | ||
@@ -48,4 +57,12 @@ if (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) { | ||
@@ -55,4 +72,12 @@ if (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) { | ||
@@ -62,3 +87,4 @@ if (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 | ||
| }); | ||
@@ -70,1 +96,8 @@ ``` | ||
| 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) |
+35
-33
| var sharp = require("../index"); | ||
| var imagemagick = require("imagemagick"); | ||
| var assert = require("assert"); | ||
| var Benchmark = require("benchmark"); | ||
| // http://www.flickr.com/photos/grizdave/2569067123/ | ||
| var input = __dirname + "/2569067123_aca715a2ee_o.jpg"; | ||
| var input = __dirname + "/2569067123_aca715a2ee_o.jpg"; // http://www.flickr.com/photos/grizdave/2569067123/ | ||
| var output = __dirname + "/output.jpg"; | ||
| var width = 640; | ||
| var height = 480; | ||
| // imagemagick | ||
| var time = process.hrtime(); | ||
| imagemagick.resize({ | ||
| srcPath: input, | ||
| dstPath: output, | ||
| quality: 0.75, | ||
| width: width, | ||
| height: height | ||
| }, function(err) { | ||
| if (err) { | ||
| throw err; | ||
| var suite = new Benchmark.Suite; | ||
| suite.add("imagemagick", { | ||
| "defer": true, | ||
| "fn": function(deferred) { | ||
| imagemagick.resize({ | ||
| srcPath: input, | ||
| dstPath: output, | ||
| quality: 0.75, | ||
| width: width, | ||
| height: height | ||
| }, function(err) { | ||
| if (err) { | ||
| throw err; | ||
| } else { | ||
| deferred.resolve(); | ||
| } | ||
| }); | ||
| } | ||
| var diff = process.hrtime(time); | ||
| imagemagickTime = diff[0] * 1e9 + diff[1]; | ||
| console.log("imagemagick took %d nanoseconds", imagemagickTime); | ||
| // sharp | ||
| time = process.hrtime(); | ||
| sharp.crop(input, output, width, height, function(err) { | ||
| if (err) { | ||
| throw err; | ||
| } | ||
| 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); | ||
| }); | ||
| }); | ||
| }).add("sharp", { | ||
| "defer": true, | ||
| "fn": function(deferred) { | ||
| sharp.crop(input, output, width, height, function(err) { | ||
| if (err) { | ||
| throw err; | ||
| } else { | ||
| deferred.resolve(); | ||
| } | ||
| }); | ||
| } | ||
| }).on("cycle", function(event) { | ||
| console.log(String(event.target)); | ||
| }).on("complete", function() { | ||
| assert(this.filter("fastest").pluck("name") == "sharp"); | ||
| }).run(); |
853266
0.13%52
10.64%97
51.56%2
100%