Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f59a2aebf | ||
|
|
26fb75bf3f | ||
|
|
25e5f27785 | ||
|
|
ef62daccf9 | ||
|
|
9067c0a000 | ||
|
|
79470d2e07 | ||
|
|
3cefa6f2bf | ||
|
|
75d954a6bc | ||
|
|
1b7e3746cc | ||
|
|
29252d9dbb | ||
|
|
23e14861be | ||
|
|
97960b5f91 | ||
|
|
18c4ad9adf | ||
|
|
b240c53633 | ||
|
|
660f3d58be | ||
|
|
b6d75cda8e | ||
|
|
e07356c11c | ||
|
|
82e215a42e | ||
|
|
cc1c36d891 | ||
|
|
a1a2d7de5c | ||
|
|
6dce2deb82 | ||
|
|
cdad84edc6 | ||
|
|
de842a67d8 | ||
|
|
918bbe88c6 | ||
|
|
7d3891989c | ||
|
|
168fe7c8d9 | ||
|
|
29ab8408fb | ||
|
|
692e2d4df4 | ||
|
|
85d86dbede | ||
|
|
ce2d7b8efc |
4
.gitignore
vendored
@@ -4,6 +4,6 @@ coverage
|
||||
test/bench/node_modules
|
||||
test/fixtures/output*
|
||||
test/leak/libvips.supp
|
||||
|
||||
# Mac OS X
|
||||
lib
|
||||
include
|
||||
.DS_Store
|
||||
|
||||
@@ -8,3 +8,5 @@ test
|
||||
.travis.yml
|
||||
appveyor.yml
|
||||
mkdocs.yml
|
||||
lib
|
||||
include
|
||||
|
||||
@@ -4,6 +4,8 @@ node_js:
|
||||
- "0.12"
|
||||
- "iojs-v2"
|
||||
- "iojs-v3"
|
||||
- "4"
|
||||
sudo: 9000
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
|
||||
10
appveyor.yml
@@ -3,18 +3,18 @@ version: "{build}"
|
||||
build: off
|
||||
platform: x64
|
||||
environment:
|
||||
VIPS_VERSION_MAJOR_MINOR: 8.0
|
||||
VIPS_VERSION_PATCH: 2
|
||||
VIPS_VERSION_MAJOR_MINOR: 8.1
|
||||
VIPS_VERSION_PATCH: 1
|
||||
VIPS_WARNING: 0
|
||||
matrix:
|
||||
- nodejs_version: "0.10"
|
||||
nodejs_exec: "node"
|
||||
- nodejs_version: "0.12"
|
||||
nodejs_exec: "node"
|
||||
- nodejs_version: "2"
|
||||
nodejs_exec: "iojs"
|
||||
- nodejs_version: "3"
|
||||
nodejs_exec: "iojs"
|
||||
- nodejs_version: "4"
|
||||
nodejs_exec: "node"
|
||||
install:
|
||||
- ps: $env:VIPS_VERSION = "$env:VIPS_VERSION_MAJOR_MINOR.$env:VIPS_VERSION_PATCH"
|
||||
- ps: Write-Output "Fetching http://www.vips.ecs.soton.ac.uk/supported/$env:VIPS_VERSION_MAJOR_MINOR/win32/vips-dev-$env:VIPS_VERSION.zip"
|
||||
@@ -23,6 +23,6 @@ install:
|
||||
- ps: $env:VIPS_HOME = "c:\vips-dev-$env:VIPS_VERSION"
|
||||
- ps: $env:PATH = "$env:VIPS_HOME\bin;$env:PATH"
|
||||
- ps: Install-Product node $env:nodejs_version x86
|
||||
- npm install --arch=ia32 --msvs_version=2013
|
||||
- npm install --arch=ia32
|
||||
test_script:
|
||||
- npm run-script test-win32-%nodejs_exec%
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
{
|
||||
'targets': [{
|
||||
'target_name': 'sharp',
|
||||
'variables': {
|
||||
'runtime_link%':'shared',
|
||||
},
|
||||
'sources': [
|
||||
'src/common.cc',
|
||||
'src/metadata.cc',
|
||||
@@ -51,6 +54,11 @@
|
||||
'include_dirs': [
|
||||
'<!(PKG_CONFIG_PATH="<(PKG_CONFIG_PATH)" pkg-config --cflags vips glib-2.0)',
|
||||
'<!(node -e "require(\'nan\')")'
|
||||
],
|
||||
'conditions': [
|
||||
['runtime_link == "static"', {
|
||||
'libraries': ['<!(PKG_CONFIG_PATH="<(PKG_CONFIG_PATH)" pkg-config --libs vips --static)']
|
||||
}]
|
||||
]
|
||||
}]
|
||||
],
|
||||
|
||||
17
docs/api.md
@@ -11,7 +11,7 @@ var sharp = require('sharp');
|
||||
Constructor to which further methods are chained. `input`, if present, can be one of:
|
||||
|
||||
* Buffer containing JPEG, PNG, WebP, GIF* or TIFF image data, or
|
||||
* String containing the filename of an image, with most major formats supported.
|
||||
* String containing the path to an image file, with most major formats supported.
|
||||
|
||||
The object returned implements the
|
||||
[stream.Duplex](http://nodejs.org/api/stream.html#stream_class_stream_duplex) class.
|
||||
@@ -111,7 +111,8 @@ Crop the resized image to the exact size specified, the default behaviour.
|
||||
|
||||
`gravity`, if present, is a String or an attribute of the `sharp.gravity` Object e.g. `sharp.gravity.north`.
|
||||
|
||||
Possible values are `north`, `east`, `south`, `west`, `center` and `centre`. The default gravity is `center`/`centre`.
|
||||
Possible values are `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `center` and `centre`.
|
||||
The default gravity is `center`/`centre`.
|
||||
|
||||
```javascript
|
||||
var transformer = sharp()
|
||||
@@ -327,7 +328,7 @@ When a `radius` is provided, performs a slower, more accurate sharpen of the L c
|
||||
|
||||
Apply a gamma correction by reducing the encoding (darken) pre-resize at a factor of `1/gamma` then increasing the encoding (brighten) post-resize at a factor of `gamma`.
|
||||
|
||||
`gamma`, if present, is a Number betweem 1 and 3. The default value is `2.2`, a suitable approximation for sRGB images.
|
||||
`gamma`, if present, is a Number between 1 and 3. The default value is `2.2`, a suitable approximation for sRGB images.
|
||||
|
||||
This can improve the perceived brightness of a resized image in non-linear colour spaces.
|
||||
|
||||
@@ -345,13 +346,13 @@ The output image will still be web-friendly sRGB and contain three (identical) c
|
||||
|
||||
Enhance output image contrast by stretching its luminance to cover the full dynamic range. This typically reduces performance by 30%.
|
||||
|
||||
#### overlayWith(filename)
|
||||
#### overlayWith(path)
|
||||
|
||||
_Experimental_
|
||||
|
||||
Alpha composite `filename` over the processed (resized, extracted) image. The dimensions of the two images must match.
|
||||
Alpha composite image at `path` over the processed (resized, extracted) image. The dimensions of the two images must match.
|
||||
|
||||
* `filename` is a String containing the filename of an image with an alpha channel.
|
||||
* `path` is a String containing the path to an image file with an alpha channel.
|
||||
|
||||
```javascript
|
||||
sharp('input.png')
|
||||
@@ -374,9 +375,9 @@ sharp('input.png')
|
||||
|
||||
### Output
|
||||
|
||||
#### toFile(filename, [callback])
|
||||
#### toFile(path, [callback])
|
||||
|
||||
`filename` is a String containing the filename to write the image data to. The format is inferred from the extension, with JPEG, PNG, WebP, TIFF and DZI supported.
|
||||
`path` is a String containing the path to write the image data to. The format is inferred from the extension, with JPEG, PNG, WebP, TIFF and DZI supported.
|
||||
|
||||
`callback`, if present, is called with two arguments `(err, info)` where:
|
||||
|
||||
|
||||
@@ -2,6 +2,26 @@
|
||||
|
||||
### v0.11 - "*knife*"
|
||||
|
||||
#### v0.11.4 - 5<sup>th</sup> November 2015
|
||||
|
||||
* Add corners, e.g. `northeast`, to existing `gravity` option.
|
||||
[#291](https://github.com/lovell/sharp/pull/291)
|
||||
[@brandonaaron](https://github.com/brandonaaron)
|
||||
|
||||
* Ensure correct auto-rotation for EXIF Orientation values 2 and 4.
|
||||
[#288](https://github.com/lovell/sharp/pull/288)
|
||||
[@brandonaaron](https://github.com/brandonaaron)
|
||||
|
||||
* Make static linking possible via `--runtime_link` install option.
|
||||
[#287](https://github.com/lovell/sharp/pull/287)
|
||||
[@vlapo](https://github.com/vlapo)
|
||||
|
||||
#### v0.11.3 - 8<sup>th</sup> September 2015
|
||||
|
||||
* Intrepret blurSigma, sharpenFlat, and sharpenJagged as double precision.
|
||||
[#263](https://github.com/lovell/sharp/pull/263)
|
||||
[@chrisriley](https://github.com/chrisriley)
|
||||
|
||||
#### v0.11.2 - 28<sup>th</sup> August 2015
|
||||
|
||||
* Allow crop gravity to be provided as a String.
|
||||
|
||||
@@ -7,8 +7,8 @@ npm install sharp
|
||||
### Prerequisites
|
||||
|
||||
* Node.js v0.10+ or io.js
|
||||
* [libvips](https://github.com/jcupitt/libvips) v7.40.0+ (7.42.0+ recommended)
|
||||
* C++11 compatible compiler such as gcc 4.6+, clang 3.0+ or MSVC 2013 (io.js v3+ requires gcc 4.8+)
|
||||
* [libvips](https://github.com/jcupitt/libvips) v7.40.0+ (8.1.1+ recommended)
|
||||
* C++11 compatible compiler such as gcc 4.6+, clang 3.0+ or MSVC 2013 (Node v4+ requires gcc 4.8+)
|
||||
|
||||
### Linux
|
||||
|
||||
@@ -19,11 +19,12 @@ For a system-wide installation of the most suitable version of
|
||||
libvips and its dependencies on the following Operating Systems:
|
||||
|
||||
* Debian 7, 8
|
||||
* Ubuntu 12.04, 14.04, 14.10, 15.04
|
||||
* Ubuntu 12.04, 14.04, 14.10, 15.04, 15.10
|
||||
* Mint 13, 17
|
||||
* Elementary 0.3
|
||||
* RHEL/Centos/Scientific 6, 7
|
||||
* Fedora 21, 22
|
||||
* Amazon Linux 2014.09, 2015.03
|
||||
* Amazon Linux 2015.03, 2015.09
|
||||
* OpenSuse 13
|
||||
|
||||
run the following as a user with `sudo` access:
|
||||
|
||||
@@ -3,18 +3,17 @@
|
||||
### Test environment
|
||||
|
||||
* AWS EC2 [c4.xlarge](http://aws.amazon.com/ec2/instance-types/#c4)
|
||||
* Ubuntu 15.04
|
||||
* Node.js 0.12.7
|
||||
* libvips 8.0.2
|
||||
* liborc 0.4.22
|
||||
* Amazon Linux AMI 2015.09
|
||||
* Node.js v4.1.2
|
||||
|
||||
### The contenders
|
||||
|
||||
* [lwip](https://www.npmjs.com/package/lwip) 0.0.7 - Wrapper around CImg, compiles dependencies from source
|
||||
* [imagemagick-native](https://www.npmjs.com/package/imagemagick-native) git@45d4e2e - Wrapper around libmagick++, supports Buffers only.
|
||||
* [imagemagick](https://www.npmjs.com/package/imagemagick) 0.1.3 - Supports filesystem only and "*has been unmaintained for a long time*".
|
||||
* [gm](https://www.npmjs.com/package/gm) 1.18.1 - Fully featured wrapper around GraphicsMagick's `convert` command line utility.
|
||||
* sharp 0.11.0 - Caching within libvips disabled to ensure a fair comparison.
|
||||
* [jimp](https://www.npmjs.com/package/jimp) v0.2.8 - Image processing in pure JavaScript.
|
||||
* [lwip](https://www.npmjs.com/package/lwip) v0.0.8 - Wrapper around CImg, compiles dependencies from source.
|
||||
* ~~[imagemagick-native](https://www.npmjs.com/package/imagemagick-native)~~ - Wrapper around libmagick++, supports Buffers only. Does not currently work with Node.js v4.
|
||||
* [imagemagick](https://www.npmjs.com/package/imagemagick) v0.1.3 - Supports filesystem only and "*has been unmaintained for a long time*".
|
||||
* [gm](https://www.npmjs.com/package/gm) v1.20.0 - Fully featured wrapper around GraphicsMagick's `convert` command line utility.
|
||||
* sharp v0.11.3 / libvips v8.1.0 - Caching within libvips disabled to ensure a fair comparison.
|
||||
|
||||
### The task
|
||||
|
||||
@@ -22,19 +21,20 @@ Decompress a 2725x2225 JPEG image, resize to 720x480 using bilinear interpolatio
|
||||
|
||||
### Results
|
||||
|
||||
| Module | Input | Output | Ops/sec | Speed-up |
|
||||
| :----------------- | :----- | :----- | ------: | -------: |
|
||||
| lwip | file | file | 1.75 | 1 |
|
||||
| lwip | buffer | buffer | 2.21 | 1.3 |
|
||||
| imagemagick-native | buffer | buffer | 7.13 | 4.1 |
|
||||
| gm | buffer | buffer | 7.27 | 4.2 |
|
||||
| gm | file | file | 7.33 | 4.2 |
|
||||
| imagemagick | file | file | 10.04 | 5.7 |
|
||||
| sharp | stream | stream | 23.12 | 13.2 |
|
||||
| sharp | file | file | 24.43 | 14.0 |
|
||||
| sharp | file | buffer | 24.55 | 14.0 |
|
||||
| sharp | buffer | file | 24.86 | 14.2 |
|
||||
| sharp | buffer | buffer | 24.92 | 14.2 |
|
||||
| Module | Input | Output | Ops/sec | Speed-up |
|
||||
| :---------- | :----- | :----- | ------: | -------: |
|
||||
| jimp | file | file | 0.94 | 1.0 |
|
||||
| jimp | buffer | buffer | 1.12 | 1.2 |
|
||||
| lwip | file | file | 1.12 | 1.2 |
|
||||
| lwip | buffer | buffer | 1.13 | 1.2 |
|
||||
| gm | buffer | buffer | 5.50 | 5.9 |
|
||||
| gm | file | file | 5.55 | 5.9 |
|
||||
| imagemagick | file | file | 8.66 | 9.2 |
|
||||
| sharp | stream | stream | 16.33 | 17.4 |
|
||||
| sharp | file | file | 16.88 | 18.0 |
|
||||
| sharp | file | buffer | 16.90 | 18.1 |
|
||||
| sharp | buffer | file | 16.99 | 18.1 |
|
||||
| sharp | buffer | buffer | 17.06 | 18.1 |
|
||||
|
||||
Greater performance can be expected with caching enabled (default) and using 8+ core machines.
|
||||
|
||||
@@ -57,7 +57,9 @@ sudo apt-get install imagemagick graphicsmagick libmagick++-dev
|
||||
|
||||
```sh
|
||||
git clone https://github.com/lovell/sharp.git
|
||||
cd sharp/test/bench
|
||||
cd sharp
|
||||
npm install
|
||||
cd test/bench
|
||||
npm install
|
||||
npm test
|
||||
```
|
||||
|
||||
4
index.js
@@ -137,11 +137,11 @@ Sharp.prototype._write = function(chunk, encoding, callback) {
|
||||
};
|
||||
|
||||
// Crop this part of the resized image (Center/Centre, North, East, South, West)
|
||||
module.exports.gravity = {'center': 0, 'centre': 0, 'north': 1, 'east': 2, 'south': 3, 'west': 4};
|
||||
module.exports.gravity = {'center': 0, 'centre': 0, 'north': 1, 'east': 2, 'south': 3, 'west': 4, 'northeast': 5, 'southeast': 6, 'southwest': 7, 'northwest': 8};
|
||||
|
||||
Sharp.prototype.crop = function(gravity) {
|
||||
this.options.canvas = 'crop';
|
||||
if (typeof gravity === 'number' && !Number.isNaN(gravity) && gravity >= 0 && gravity <= 4) {
|
||||
if (typeof gravity === 'number' && !Number.isNaN(gravity) && gravity >= 0 && gravity <= 8) {
|
||||
this.options.gravity = gravity;
|
||||
} else if (typeof gravity === 'string' && typeof module.exports.gravity[gravity] === 'number') {
|
||||
this.options.gravity = module.exports.gravity[gravity];
|
||||
|
||||
21
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sharp",
|
||||
"version": "0.11.2",
|
||||
"version": "0.11.4",
|
||||
"author": "Lovell Fuller <npm@lovell.info>",
|
||||
"contributors": [
|
||||
"Pierre Inglebert <pierre.inglebert@gmail.com>",
|
||||
@@ -16,7 +16,8 @@
|
||||
"Linus Unnebäck <linus@folkdatorn.se>",
|
||||
"Victor Mateevitsi <mvictoras@gmail.com>",
|
||||
"Alaric Holloway <alaric.holloway@gmail.com>",
|
||||
"Bernhard K. Weisshuhn <bkw@codingforce.com>"
|
||||
"Bernhard K. Weisshuhn <bkw@codingforce.com>",
|
||||
"Chris Riley <criley@primedia.com>"
|
||||
],
|
||||
"description": "High performance Node.js module to resize JPEG, PNG, WebP and TIFF images using the libvips library",
|
||||
"scripts": {
|
||||
@@ -45,21 +46,21 @@
|
||||
"vips"
|
||||
],
|
||||
"dependencies": {
|
||||
"bluebird": "^2.9.34",
|
||||
"bluebird": "^3.0.5",
|
||||
"color": "^0.10.1",
|
||||
"nan": "^2.0.8",
|
||||
"semver": "^5.0.1"
|
||||
"nan": "^2.1.0",
|
||||
"semver": "^5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"async": "^1.4.2",
|
||||
"async": "^1.5.0",
|
||||
"coveralls": "^2.11.4",
|
||||
"exif-reader": "1.0.0",
|
||||
"icc": "^0.0.2",
|
||||
"istanbul": "^0.3.18",
|
||||
"mocha": "^2.2.5",
|
||||
"mocha-jshint": "^2.2.3",
|
||||
"istanbul": "^0.4.0",
|
||||
"mocha": "^2.3.3",
|
||||
"mocha-jshint": "^2.2.5",
|
||||
"node-cpplint": "^0.4.0",
|
||||
"rimraf": "^2.4.2",
|
||||
"rimraf": "^2.4.3",
|
||||
"bufferutil": "^1.2.1"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -4,16 +4,18 @@
|
||||
# Currently supports:
|
||||
# * Debian Linux
|
||||
# * Debian 7, 8
|
||||
# * Ubuntu 12.04, 14.04, 14.10, 15.04
|
||||
# * Ubuntu 12.04, 14.04, 14.10, 15.04, 15.10
|
||||
# * Mint 13, 17
|
||||
# * Elementary 0.3
|
||||
# * Red Hat Linux
|
||||
# * RHEL/Centos/Scientific 6, 7
|
||||
# * Fedora 21, 22
|
||||
# * Amazon Linux 2014.09, 2015.03
|
||||
# * Amazon Linux 2015.03, 2015.09
|
||||
# * OpenSuse 13
|
||||
|
||||
vips_version_minimum=7.40.0
|
||||
vips_version_latest_major_minor=8.0
|
||||
vips_version_latest_patch=2
|
||||
vips_version_latest_major_minor=8.1
|
||||
vips_version_latest_patch=1
|
||||
|
||||
openslide_version_minimum=3.4.0
|
||||
openslide_version_latest_major_minor=3.4
|
||||
@@ -24,7 +26,7 @@ install_libvips_from_source() {
|
||||
curl -O http://www.vips.ecs.soton.ac.uk/supported/$vips_version_latest_major_minor/vips-$vips_version_latest_major_minor.$vips_version_latest_patch.tar.gz
|
||||
tar zvxf vips-$vips_version_latest_major_minor.$vips_version_latest_patch.tar.gz
|
||||
cd vips-$vips_version_latest_major_minor.$vips_version_latest_patch
|
||||
./configure --disable-debug --disable-docs --disable-static --disable-introspection --enable-cxx=yes --without-python --without-orc --without-fftw $1
|
||||
./configure --disable-debug --disable-docs --disable-static --disable-introspection --disable-dependency-tracking --enable-cxx=yes --without-python --without-orc --without-fftw $1
|
||||
make
|
||||
make install
|
||||
cd ..
|
||||
@@ -125,12 +127,12 @@ if [ $enable_openslide -eq 1 ] && [ -z $vips_with_openslide ] && [ $openslide_ex
|
||||
DISTRO=$(lsb_release -c -s)
|
||||
echo "Detected Debian Linux '$DISTRO'"
|
||||
case "$DISTRO" in
|
||||
jessie|vivid)
|
||||
jessie|vivid|wily)
|
||||
# Debian 8, Ubuntu 15
|
||||
echo "Installing libopenslide via apt-get"
|
||||
apt-get install -y libopenslide-dev
|
||||
;;
|
||||
trusty|utopic|qiana|rebecca|rafaela)
|
||||
trusty|utopic|qiana|rebecca|rafaela|freya)
|
||||
# Ubuntu 14, Mint 17
|
||||
echo "Installing libopenslide dependencies via apt-get"
|
||||
apt-get install -y automake build-essential curl zlib1g-dev libopenjpeg-dev libpng12-dev libjpeg-dev libtiff5-dev libgdk-pixbuf2.0-dev libxml2-dev libsqlite3-dev libcairo2-dev libglib2.0-dev sqlite3 libsqlite3-dev
|
||||
@@ -209,7 +211,7 @@ if [ -f /etc/debian_version ]; then
|
||||
DISTRO=$(lsb_release -c -s)
|
||||
echo "Detected Debian Linux '$DISTRO'"
|
||||
case "$DISTRO" in
|
||||
jessie|vivid)
|
||||
jessie|vivid|wily)
|
||||
# Debian 8, Ubuntu 15
|
||||
if [ $enable_openslide -eq 1 ]; then
|
||||
echo "Recompiling vips with openslide support"
|
||||
@@ -219,7 +221,7 @@ if [ -f /etc/debian_version ]; then
|
||||
apt-get install -y libvips-dev libgsf-1-dev
|
||||
fi
|
||||
;;
|
||||
trusty|utopic|qiana|rebecca|rafaela)
|
||||
trusty|utopic|qiana|rebecca|rafaela|freya)
|
||||
# Ubuntu 14, Mint 17
|
||||
echo "Installing libvips dependencies via apt-get"
|
||||
apt-get install -y automake build-essential gobject-introspection gtk-doc-tools libglib2.0-dev libjpeg-dev libpng12-dev libwebp-dev libtiff5-dev libexif-dev libgsf-1-dev liblcms2-dev libxml2-dev swig libmagickcore-dev curl
|
||||
@@ -247,7 +249,7 @@ elif [ -f /etc/redhat-release ]; then
|
||||
# RHEL/CentOS 7
|
||||
echo "Installing libvips dependencies via yum"
|
||||
yum groupinstall -y "Development Tools"
|
||||
yum install -y gtk-doc libxml2-devel libjpeg-turbo-devel libpng-devel libtiff-devel libexif-devel libgsf-devel lcms-devel ImageMagick-devel gobject-introspection-devel libwebp-devel curl
|
||||
yum install -y gtk-doc libxml2-devel libjpeg-turbo-devel libpng-devel libtiff-devel libexif-devel libgsf-devel lcms2-devel ImageMagick-devel gobject-introspection-devel libwebp-devel curl
|
||||
install_libvips_from_source "--prefix=/usr"
|
||||
;;
|
||||
"Red Hat Enterprise Linux release 6."*|"CentOS release 6."*|"Scientific Linux release 6."*)
|
||||
@@ -283,12 +285,12 @@ elif [ -f /etc/system-release ]; then
|
||||
# Probably Amazon Linux
|
||||
RELEASE=$(cat /etc/system-release)
|
||||
case $RELEASE in
|
||||
"Amazon Linux AMI release 2014.09"|"Amazon Linux AMI release 2015.03")
|
||||
"Amazon Linux AMI release 2015.03"|"Amazon Linux AMI release 2015.09")
|
||||
# Amazon Linux
|
||||
echo "Detected '$RELEASE'"
|
||||
echo "Installing libvips dependencies via yum"
|
||||
yum groupinstall -y "Development Tools"
|
||||
yum install -y gtk-doc libxml2-devel libjpeg-turbo-devel libpng-devel libtiff-devel libexif-devel libgsf-devel lcms-devel ImageMagick-devel gobject-introspection-devel libwebp-devel curl
|
||||
yum install -y gtk-doc libxml2-devel libjpeg-turbo-devel libpng-devel libtiff-devel libexif-devel libgsf-devel lcms2-devel ImageMagick-devel gobject-introspection-devel libwebp-devel curl
|
||||
install_libvips_from_source "--prefix=/usr"
|
||||
;;
|
||||
*)
|
||||
|
||||
@@ -250,11 +250,16 @@ class PipelineWorker : public AsyncWorker {
|
||||
// Calculate angle of rotation
|
||||
Angle rotation;
|
||||
bool flip;
|
||||
std::tie(rotation, flip) = CalculateRotationAndFlip(baton->angle, image);
|
||||
bool flop;
|
||||
std::tie(rotation, flip, flop) = CalculateRotationAndFlip(baton->angle, image);
|
||||
if (flip && !baton->flip) {
|
||||
// Add flip operation due to EXIF mirroring
|
||||
baton->flip = TRUE;
|
||||
}
|
||||
if (flop && !baton->flop) {
|
||||
// Add flip operation due to EXIF mirroring
|
||||
baton->flop = TRUE;
|
||||
}
|
||||
|
||||
// Rotate pre-extract
|
||||
if (baton->rotateBeforePreExtract && rotation != Angle::D0) {
|
||||
@@ -1041,18 +1046,19 @@ class PipelineWorker : public AsyncWorker {
|
||||
2. Use input image EXIF Orientation header - supports mirroring
|
||||
3. Otherwise default to zero, i.e. no rotation
|
||||
*/
|
||||
std::tuple<Angle, bool>
|
||||
std::tuple<Angle, bool, bool>
|
||||
CalculateRotationAndFlip(int const angle, VipsImage const *input) {
|
||||
Angle rotate = Angle::D0;
|
||||
bool flip = FALSE;
|
||||
bool flop = FALSE;
|
||||
if (angle == -1) {
|
||||
switch(ExifOrientation(input)) {
|
||||
case 6: rotate = Angle::D90; break;
|
||||
case 3: rotate = Angle::D180; break;
|
||||
case 8: rotate = Angle::D270; break;
|
||||
case 2: flip = TRUE; break; // flip 1
|
||||
case 2: flop = TRUE; break; // flop 1
|
||||
case 7: flip = TRUE; rotate = Angle::D90; break; // flip 6
|
||||
case 4: flip = TRUE; rotate = Angle::D180; break; // flip 3
|
||||
case 4: flop = TRUE; rotate = Angle::D180; break; // flop 3
|
||||
case 5: flip = TRUE; rotate = Angle::D270; break; // flip 8
|
||||
}
|
||||
} else {
|
||||
@@ -1064,7 +1070,7 @@ class PipelineWorker : public AsyncWorker {
|
||||
rotate = Angle::D270;
|
||||
}
|
||||
}
|
||||
return std::make_tuple(rotate, flip);
|
||||
return std::make_tuple(rotate, flip, flop);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1090,6 +1096,16 @@ class PipelineWorker : public AsyncWorker {
|
||||
case 4: // West
|
||||
top = (inHeight - outHeight + 1) / 2;
|
||||
break;
|
||||
case 5: // Northeast
|
||||
left = inWidth - outWidth;
|
||||
break;
|
||||
case 6: // Southeast
|
||||
left = inWidth - outWidth;
|
||||
top = inHeight - outHeight;
|
||||
case 7: // Southwest
|
||||
top = inHeight - outHeight;
|
||||
case 8: // Northwest
|
||||
break;
|
||||
default: // Centre
|
||||
left = (inWidth - outWidth + 1) / 2;
|
||||
top = (inHeight - outHeight + 1) / 2;
|
||||
@@ -1202,10 +1218,10 @@ NAN_METHOD(pipeline) {
|
||||
baton->interpolator = *Utf8String(Get(options, New("interpolator").ToLocalChecked()).ToLocalChecked());
|
||||
// Operators
|
||||
baton->flatten = To<bool>(Get(options, New("flatten").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->blurSigma = To<int32_t>(Get(options, New("blurSigma").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->blurSigma = To<double>(Get(options, New("blurSigma").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->sharpenRadius = To<int32_t>(Get(options, New("sharpenRadius").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->sharpenFlat = To<int32_t>(Get(options, New("sharpenFlat").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->sharpenJagged = To<int32_t>(Get(options, New("sharpenJagged").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->sharpenFlat = To<double>(Get(options, New("sharpenFlat").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->sharpenJagged = To<double>(Get(options, New("sharpenJagged").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->gamma = To<int32_t>(Get(options, New("gamma").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->greyscale = To<bool>(Get(options, New("greyscale").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
baton->normalize = To<bool>(Get(options, New("normalize").ToLocalChecked()).ToLocalChecked()).FromJust();
|
||||
@@ -1240,3 +1256,4 @@ NAN_METHOD(pipeline) {
|
||||
Local<Value> queueLength[1] = { New<Uint32>(counterQueue) };
|
||||
queueListener->Call(1, queueLength);
|
||||
}
|
||||
|
||||
|
||||
11
test/bench/package.json
Executable file → Normal file
@@ -8,13 +8,14 @@
|
||||
"test": "node perf && node random && node parallel"
|
||||
},
|
||||
"devDependencies": {
|
||||
"async": "^1.4.2",
|
||||
"benchmark": "^1.0.0",
|
||||
"gm": "^1.20.0",
|
||||
"imagemagick": "^0.1.3",
|
||||
"imagemagick-native": "^1.8.0",
|
||||
"gm": "^1.18.1",
|
||||
"lwip": "^0.0.7",
|
||||
"async": "^1.4.2",
|
||||
"semver": "^5.0.1",
|
||||
"benchmark": "^1.0.0"
|
||||
"jimp": "^0.2.8",
|
||||
"lwip": "^0.0.8",
|
||||
"semver": "^5.0.3"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
|
||||
@@ -10,6 +10,7 @@ var semver = require('semver');
|
||||
// Contenders
|
||||
var gm = require('gm');
|
||||
var imagemagick = require('imagemagick');
|
||||
var jimp = require('jimp');
|
||||
var sharp = require('../../index');
|
||||
var imagemagickNative;
|
||||
try {
|
||||
@@ -39,6 +40,48 @@ async.series({
|
||||
jpeg: function(callback) {
|
||||
var inputJpgBuffer = fs.readFileSync(fixtures.inputJpg);
|
||||
var jpegSuite = new Benchmark.Suite('jpeg');
|
||||
// jimp
|
||||
jpegSuite.add('jimp-buffer-buffer', {
|
||||
defer: true,
|
||||
fn: function(deferred) {
|
||||
new jimp(inputJpgBuffer, function(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
this
|
||||
.resize(width, height)
|
||||
.quality(80)
|
||||
.getBuffer(jimp.MIME_JPEG, function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}).add('jimp-file-file', {
|
||||
defer: true,
|
||||
fn: function(deferred) {
|
||||
new jimp(fixtures.inputJpg, function(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
this
|
||||
.resize(width, height)
|
||||
.quality(80)
|
||||
.write(fixtures.outputJpg, function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// lwip
|
||||
if (typeof lwip !== 'undefined') {
|
||||
jpegSuite.add('lwip-file-file', {
|
||||
@@ -471,6 +514,46 @@ async.series({
|
||||
png: function(callback) {
|
||||
var inputPngBuffer = fs.readFileSync(fixtures.inputPng);
|
||||
var pngSuite = new Benchmark.Suite('png');
|
||||
// jimp
|
||||
pngSuite.add('jimp-buffer-buffer', {
|
||||
defer: true,
|
||||
fn: function(deferred) {
|
||||
new jimp(inputPngBuffer, function(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
this
|
||||
.resize(width, height)
|
||||
.getBuffer(jimp.MIME_PNG, function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}).add('jimp-file-file', {
|
||||
defer: true,
|
||||
fn: function(deferred) {
|
||||
new jimp(fixtures.inputPng, function(err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
this
|
||||
.resize(width, height)
|
||||
.write(fixtures.outputPng, function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// lwip
|
||||
if (typeof lwip !== 'undefined') {
|
||||
pngSuite.add('lwip-buffer-buffer', {
|
||||
|
||||
BIN
test/fixtures/Landscape_1.jpg
vendored
Executable file
|
After Width: | Height: | Size: 136 KiB |
BIN
test/fixtures/Landscape_2.jpg
vendored
Executable file
|
After Width: | Height: | Size: 134 KiB |
BIN
test/fixtures/Landscape_3.jpg
vendored
Executable file
|
After Width: | Height: | Size: 138 KiB |
BIN
test/fixtures/Landscape_4.jpg
vendored
Executable file
|
After Width: | Height: | Size: 137 KiB |
0
test/fixtures/Landscape_5.jpg
vendored
Normal file → Executable file
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
BIN
test/fixtures/Landscape_6.jpg
vendored
Executable file
|
After Width: | Height: | Size: 134 KiB |
BIN
test/fixtures/Landscape_7.jpg
vendored
Executable file
|
After Width: | Height: | Size: 137 KiB |
0
test/fixtures/Landscape_8.jpg
vendored
Normal file → Executable file
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 138 KiB |
BIN
test/fixtures/Portrait_1.jpg
vendored
Executable file
|
After Width: | Height: | Size: 126 KiB |
BIN
test/fixtures/Portrait_2.jpg
vendored
Executable file
|
After Width: | Height: | Size: 133 KiB |
BIN
test/fixtures/Portrait_3.jpg
vendored
Executable file
|
After Width: | Height: | Size: 133 KiB |
BIN
test/fixtures/Portrait_4.jpg
vendored
Executable file
|
After Width: | Height: | Size: 128 KiB |
BIN
test/fixtures/Portrait_5.jpg
vendored
Executable file
|
After Width: | Height: | Size: 131 KiB |
BIN
test/fixtures/Portrait_6.jpg
vendored
Executable file
|
After Width: | Height: | Size: 133 KiB |
BIN
test/fixtures/Portrait_7.jpg
vendored
Executable file
|
After Width: | Height: | Size: 132 KiB |
BIN
test/fixtures/Portrait_8.jpg
vendored
Executable file
|
After Width: | Height: | Size: 129 KiB |
BIN
test/fixtures/expected/Landscape_1-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 109 KiB |
BIN
test/fixtures/expected/Landscape_2-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
test/fixtures/expected/Landscape_3-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
test/fixtures/expected/Landscape_4-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
test/fixtures/expected/Landscape_5-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
test/fixtures/expected/Landscape_6-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
test/fixtures/expected/Landscape_7-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
test/fixtures/expected/Landscape_8-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
test/fixtures/expected/Portrait_1-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 169 KiB |
BIN
test/fixtures/expected/Portrait_2-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
test/fixtures/expected/Portrait_3-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 165 KiB |
BIN
test/fixtures/expected/Portrait_4-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
test/fixtures/expected/Portrait_5-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 172 KiB |
BIN
test/fixtures/expected/Portrait_6-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 167 KiB |
BIN
test/fixtures/expected/Portrait_7-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
test/fixtures/expected/Portrait_8-out.jpg
vendored
Normal file
|
After Width: | Height: | Size: 165 KiB |
BIN
test/fixtures/expected/blur-0.3.jpg
vendored
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
test/fixtures/expected/blur-1.jpg
vendored
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
test/fixtures/expected/blur-10.jpg
vendored
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
test/fixtures/expected/blur-mild.jpg
vendored
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
test/fixtures/expected/sharpen-10.jpg
vendored
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
test/fixtures/expected/sharpen-3-0.5-2.5.jpg
vendored
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
test/fixtures/expected/sharpen-5-2-4.jpg
vendored
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
test/fixtures/expected/sharpen-mild.jpg
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
18
test/fixtures/index.js
vendored
@@ -40,6 +40,24 @@ var fingerprint = function(image, callback) {
|
||||
|
||||
module.exports = {
|
||||
|
||||
inputJpgWithLandscapeExif1: getPath('Landscape_1.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithLandscapeExif2: getPath('Landscape_2.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithLandscapeExif3: getPath('Landscape_3.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithLandscapeExif4: getPath('Landscape_4.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithLandscapeExif5: getPath('Landscape_5.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithLandscapeExif6: getPath('Landscape_6.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithLandscapeExif7: getPath('Landscape_7.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithLandscapeExif8: getPath('Landscape_8.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
|
||||
inputJpgWithPortraitExif1: getPath('Portrait_1.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithPortraitExif2: getPath('Portrait_2.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithPortraitExif3: getPath('Portrait_3.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithPortraitExif4: getPath('Portrait_4.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithPortraitExif5: getPath('Portrait_5.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithPortraitExif6: getPath('Portrait_6.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithPortraitExif7: getPath('Portrait_7.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
inputJpgWithPortraitExif8: getPath('Portrait_8.jpg'), // https://github.com/recurser/exif-orientation-examples
|
||||
|
||||
inputJpg: getPath('2569067123_aca715a2ee_o.jpg'), // http://www.flickr.com/photos/grizdave/2569067123/
|
||||
inputJpgWithExif: getPath('Landscape_8.jpg'), // https://github.com/recurser/exif-orientation-examples/blob/master/Landscape_8.jpg
|
||||
inputJpgWithExifMirroring: getPath('Landscape_5.jpg'), // https://github.com/recurser/exif-orientation-examples/blob/master/Landscape_5.jpg
|
||||
|
||||
@@ -13,12 +13,11 @@ describe('Blur', function() {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.blur(1)
|
||||
.toFile(fixtures.path('output.blur-1.jpg'), function(err, info) {
|
||||
if (err) throw err;
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
done();
|
||||
fixtures.assertSimilar(fixtures.expected('blur-1.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,12 +25,11 @@ describe('Blur', function() {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.blur(10)
|
||||
.toFile(fixtures.path('output.blur-10.jpg'), function(err, info) {
|
||||
if (err) throw err;
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
done();
|
||||
fixtures.assertSimilar(fixtures.expected('blur-10.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -39,12 +37,11 @@ describe('Blur', function() {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.blur(0.3)
|
||||
.toFile(fixtures.path('output.blur-0.3.jpg'), function(err, info) {
|
||||
if (err) throw err;
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
done();
|
||||
fixtures.assertSimilar(fixtures.expected('blur-0.3.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -52,24 +49,18 @@ describe('Blur', function() {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.blur()
|
||||
.toFile(fixtures.path('output.blur-mild.jpg'), function(err, info) {
|
||||
if (err) throw err;
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
done();
|
||||
fixtures.assertSimilar(fixtures.expected('blur-mild.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('invalid radius', function(done) {
|
||||
var isValid = true;
|
||||
try {
|
||||
it('invalid radius', function() {
|
||||
assert.throws(function() {
|
||||
sharp(fixtures.inputJpg).blur(0.1);
|
||||
} catch (err) {
|
||||
isValid = false;
|
||||
}
|
||||
assert.strictEqual(false, isValid);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('blurred image is smaller than non-blurred', function(done) {
|
||||
@@ -77,7 +68,6 @@ describe('Blur', function() {
|
||||
.resize(320, 240)
|
||||
.blur(false)
|
||||
.toBuffer(function(err, notBlurred, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(true, notBlurred.length > 0);
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
@@ -86,7 +76,6 @@ describe('Blur', function() {
|
||||
.resize(320, 240)
|
||||
.blur(true)
|
||||
.toBuffer(function(err, blurred, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(true, blurred.length > 0);
|
||||
assert.strictEqual(true, blurred.length < notBlurred.length);
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
|
||||
@@ -9,76 +9,119 @@ sharp.cache(0);
|
||||
|
||||
describe('Crop gravities', function() {
|
||||
|
||||
it('North', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 80)
|
||||
.crop(sharp.gravity.north)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(80, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('gravity-north.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
var testSettings = [
|
||||
{
|
||||
name: 'North',
|
||||
width: 320,
|
||||
height: 80,
|
||||
gravity: sharp.gravity.north,
|
||||
fixture: 'gravity-north.jpg'
|
||||
},
|
||||
{
|
||||
name: 'East',
|
||||
width: 80,
|
||||
height: 320,
|
||||
gravity: sharp.gravity.east,
|
||||
fixture: 'gravity-east.jpg'
|
||||
},
|
||||
{
|
||||
name: 'South',
|
||||
width: 320,
|
||||
height: 80,
|
||||
gravity: sharp.gravity.south,
|
||||
fixture: 'gravity-south.jpg'
|
||||
},
|
||||
{
|
||||
name: 'West',
|
||||
width: 80,
|
||||
height: 320,
|
||||
gravity: sharp.gravity.west,
|
||||
fixture: 'gravity-west.jpg'
|
||||
},
|
||||
{
|
||||
name: 'Center',
|
||||
width: 320,
|
||||
height: 80,
|
||||
gravity: sharp.gravity.center,
|
||||
fixture: 'gravity-center.jpg'
|
||||
},
|
||||
{
|
||||
name: 'Centre',
|
||||
width: 80,
|
||||
height: 320,
|
||||
gravity: sharp.gravity.centre,
|
||||
fixture: 'gravity-centre.jpg'
|
||||
},
|
||||
{
|
||||
name: 'Northeast',
|
||||
width: 320,
|
||||
height: 80,
|
||||
gravity: sharp.gravity.northeast,
|
||||
fixture: 'gravity-north.jpg'
|
||||
},
|
||||
{
|
||||
name: 'Northeast',
|
||||
width: 80,
|
||||
height: 320,
|
||||
gravity: sharp.gravity.northeast,
|
||||
fixture: 'gravity-east.jpg'
|
||||
},
|
||||
{
|
||||
name: 'Southeast',
|
||||
width: 320,
|
||||
height: 80,
|
||||
gravity: sharp.gravity.southeast,
|
||||
fixture: 'gravity-south.jpg'
|
||||
},
|
||||
{
|
||||
name: 'Southeast',
|
||||
width: 80,
|
||||
height: 320,
|
||||
gravity: sharp.gravity.southeast,
|
||||
fixture: 'gravity-east.jpg'
|
||||
},
|
||||
{
|
||||
name: 'Southwest',
|
||||
width: 320,
|
||||
height: 80,
|
||||
gravity: sharp.gravity.southwest,
|
||||
fixture: 'gravity-south.jpg'
|
||||
},
|
||||
{
|
||||
name: 'Southwest',
|
||||
width: 80,
|
||||
height: 320,
|
||||
gravity: sharp.gravity.southwest,
|
||||
fixture: 'gravity-west.jpg'
|
||||
},
|
||||
{
|
||||
name: 'Northwest',
|
||||
width: 320,
|
||||
height: 80,
|
||||
gravity: sharp.gravity.northwest,
|
||||
fixture: 'gravity-north.jpg'
|
||||
},
|
||||
{
|
||||
name: 'Northwest',
|
||||
width: 80,
|
||||
height: 320,
|
||||
gravity: sharp.gravity.northwest,
|
||||
fixture: 'gravity-west.jpg'
|
||||
}
|
||||
];
|
||||
|
||||
it('East', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(80, 320)
|
||||
.crop(sharp.gravity.east)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(80, info.width);
|
||||
assert.strictEqual(320, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('gravity-east.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('South', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 80)
|
||||
.crop(sharp.gravity.south)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(80, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('gravity-south.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('West', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(80, 320)
|
||||
.crop(sharp.gravity.west)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(80, info.width);
|
||||
assert.strictEqual(320, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('gravity-west.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('Center', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 80)
|
||||
.crop(sharp.gravity.center)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(80, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('gravity-center.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('Centre', function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(80, 320)
|
||||
.crop(sharp.gravity.centre)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(80, info.width);
|
||||
assert.strictEqual(320, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('gravity-centre.jpg'), data, done);
|
||||
});
|
||||
testSettings.forEach(function(settings) {
|
||||
it(settings.name, function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(settings.width, settings.height)
|
||||
.crop(settings.gravity)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(settings.width, info.width);
|
||||
assert.strictEqual(settings.height, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected(settings.fixture), data, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('allows specifying the gravity as a string', function(done) {
|
||||
@@ -95,7 +138,7 @@ describe('Crop gravities', function() {
|
||||
|
||||
it('Invalid number', function() {
|
||||
assert.throws(function() {
|
||||
sharp(fixtures.inputJpg).crop(5);
|
||||
sharp(fixtures.inputJpg).crop(9);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -9,6 +9,23 @@ sharp.cache(0);
|
||||
|
||||
describe('Rotation', function() {
|
||||
|
||||
['Landscape', 'Portrait'].forEach(function(orientation) {
|
||||
[1,2,3,4,5,6,7,8].forEach(function(exifTag) {
|
||||
it('Input image has Orientation EXIF tag value of (' + exifTag + '), auto-rotate', function(done) {
|
||||
sharp(fixtures['inputJpgWith'+orientation+'Exif'+exifTag])
|
||||
.rotate()
|
||||
.resize(320)
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(orientation === 'Landscape' ? 240 : 427, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected(orientation + '_' + exifTag + '-out.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Rotate by 90 degrees, respecting output input size', function(done) {
|
||||
sharp(fixtures.inputJpg).rotate(90).resize(320, 240).toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
|
||||
@@ -13,12 +13,11 @@ describe('Sharpen', function() {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.sharpen(10)
|
||||
.toFile(fixtures.path('output.sharpen-10.jpg'), function(err, info) {
|
||||
if (err) throw err;
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
done();
|
||||
fixtures.assertSimilar(fixtures.expected('sharpen-10.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,12 +25,11 @@ describe('Sharpen', function() {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.sharpen(3, 0.5, 2.5)
|
||||
.toFile(fixtures.path('output.sharpen-3-0.5-2.5.jpg'), function(err, info) {
|
||||
if (err) throw err;
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
done();
|
||||
fixtures.assertSimilar(fixtures.expected('sharpen-3-0.5-2.5.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -39,12 +37,11 @@ describe('Sharpen', function() {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.sharpen(5, 2, 4)
|
||||
.toFile(fixtures.path('output.sharpen-5-2-4.jpg'), function(err, info) {
|
||||
if (err) throw err;
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
done();
|
||||
fixtures.assertSimilar(fixtures.expected('sharpen-5-2-4.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -52,46 +49,30 @@ describe('Sharpen', function() {
|
||||
sharp(fixtures.inputJpg)
|
||||
.resize(320, 240)
|
||||
.sharpen()
|
||||
.toFile(fixtures.path('output.sharpen-mild.jpg'), function(err, info) {
|
||||
if (err) throw err;
|
||||
.toBuffer(function(err, data, info) {
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
assert.strictEqual(240, info.height);
|
||||
done();
|
||||
fixtures.assertSimilar(fixtures.expected('sharpen-mild.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('invalid radius', function(done) {
|
||||
var isValid = true;
|
||||
try {
|
||||
it('invalid radius', function() {
|
||||
assert.throws(function() {
|
||||
sharp(fixtures.inputJpg).sharpen(1.5);
|
||||
} catch (err) {
|
||||
isValid = false;
|
||||
}
|
||||
assert.strictEqual(false, isValid);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('invalid flat', function(done) {
|
||||
var isValid = true;
|
||||
try {
|
||||
it('invalid flat', function() {
|
||||
assert.throws(function() {
|
||||
sharp(fixtures.inputJpg).sharpen(1, -1);
|
||||
} catch (err) {
|
||||
isValid = false;
|
||||
}
|
||||
assert.strictEqual(false, isValid);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('invalid jagged', function(done) {
|
||||
var isValid = true;
|
||||
try {
|
||||
it('invalid jagged', function() {
|
||||
assert.throws(function() {
|
||||
sharp(fixtures.inputJpg).sharpen(1, 1, -1);
|
||||
} catch (err) {
|
||||
isValid = false;
|
||||
}
|
||||
assert.strictEqual(false, isValid);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('sharpened image is larger than non-sharpened', function(done) {
|
||||
@@ -99,7 +80,6 @@ describe('Sharpen', function() {
|
||||
.resize(320, 240)
|
||||
.sharpen(false)
|
||||
.toBuffer(function(err, notSharpened, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(true, notSharpened.length > 0);
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(320, info.width);
|
||||
@@ -108,7 +88,6 @@ describe('Sharpen', function() {
|
||||
.resize(320, 240)
|
||||
.sharpen(true)
|
||||
.toBuffer(function(err, sharpened, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(true, sharpened.length > 0);
|
||||
assert.strictEqual(true, sharpened.length > notSharpened.length);
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
|
||||