Compare commits

...

17 Commits

Author SHA1 Message Date
Lovell Fuller
d6051dd714 Release v0.18.2 2017-07-01 09:52:47 +01:00
Lovell Fuller
53ff061efa Document SHARP_DIST_BASE_URL #841 2017-07-01 09:44:02 +01:00
Lovell Fuller
72b0efd393 Remove possible switch case fall through
Luckily there were no side effects in this... case
2017-06-25 19:09:20 +01:00
Lovell Fuller
df97ef23d9 Document/changelog for Solus Linux support #857 2017-06-25 17:42:03 +01:00
Ekrem Karaca
f6373971bd Add support for Solus OS (#857) 2017-06-24 13:48:03 +01:00
Lovell Fuller
ec617f2489 Document minimum Node dependency of v4.5.0 #847 2017-06-20 22:05:05 +01:00
Lovell Fuller
502ae78579 Allow binary download URL override via SHARP_DIST_BASE_URL #841 2017-06-20 21:40:46 +01:00
Lovell Fuller
49297d6afb Ensure flip and flop operations work with auto-rotate #837 2017-06-19 23:42:26 +01:00
Lovell Fuller
29354badd8 Docs: add Alpine Linux install details 2017-06-19 08:13:49 +01:00
Lovell Fuller
3c4de796c8 Dependency bumps and next point release 2017-06-04 19:55:45 +01:00
Lovell Fuller
c7f4488e77 Docs and changelog entry for #828 2017-06-04 19:51:22 +01:00
Yves Bos
d8765f955d Allow xres and yres to be set for TIFF output (#828) 2017-06-03 10:52:09 +01:00
Lovell Fuller
9f20037dad Release v0.18.1 2017-05-30 21:02:35 +01:00
Lovell Fuller
2ebb090df2 Update Travis CI to Ubuntu 16.04
Rollback Appveyor CI from Node 8 to 7
2017-05-30 20:50:32 +01:00
Lovell Fuller
110fff3ab9 Replace Node 7 with Node 8 in CI environment 2017-05-30 20:32:15 +01:00
Lovell Fuller
f42a1ceab7 Recalculate residual after adjusting shrink #831 2017-05-30 20:22:15 +01:00
Lovell Fuller
9e39a7fa95 Correct shrink calc, regression introduced in e398b47 #831 2017-05-30 17:16:41 +01:00
18 changed files with 235 additions and 38 deletions

View File

@@ -1,21 +1,27 @@
language: node_js language: node_js
node_js: matrix:
- "4" include:
- "6" - os: linux
- "7" dist: trusty
os:
- linux
- osx
sudo: false sudo: false
addons: node_js: "4"
apt: - os: linux
sources: dist: trusty
- ubuntu-toolchain-r-test sudo: false
packages: node_js: "6"
- g++-4.8 - os: linux
dist: trusty
sudo: false
node_js: "8"
- os: osx
osx_image: xcode8 osx_image: xcode8
before_install: node_js: "4"
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export CXX=g++-4.8; fi - os: osx
osx_image: xcode8
node_js: "6"
- os: osx
osx_image: xcode8
node_js: "8"
after_success: after_success:
- npm install coveralls - npm install coveralls
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js - cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js

View File

@@ -9,7 +9,7 @@ const got = require('got');
const semver = require('semver'); const semver = require('semver');
const tar = require('tar'); const tar = require('tar');
const distBaseUrl = 'https://dl.bintray.com/lovell/sharp/'; const distBaseUrl = process.env.SHARP_DIST_BASE_URL || 'https://dl.bintray.com/lovell/sharp/';
// Use NPM-provided environment variable where available, falling back to require-based method for Electron // Use NPM-provided environment variable where available, falling back to require-based method for Electron
const minimumLibvipsVersion = process.env.npm_package_config_libvips || require('./package.json').config.libvips; const minimumLibvipsVersion = process.env.npm_package_config_libvips || require('./package.json').config.libvips;
@@ -73,7 +73,7 @@ module.exports.download_vips = function () {
// Ensure glibc >= 2.15 // Ensure glibc >= 2.15
const lddVersion = process.env.LDD_VERSION; const lddVersion = process.env.LDD_VERSION;
if (lddVersion) { if (lddVersion) {
if (/(glibc|gnu libc|gentoo)/i.test(lddVersion)) { if (/(glibc|gnu libc|gentoo|solus)/i.test(lddVersion)) {
const glibcVersion = lddVersion ? lddVersion.split(/\n/)[0].split(' ').slice(-1)[0].trim() : ''; const glibcVersion = lddVersion ? lddVersion.split(/\n/)[0].split(' ').slice(-1)[0].trim() : '';
if (glibcVersion && semver.lt(glibcVersion + '.0', '2.13.0')) { if (glibcVersion && semver.lt(glibcVersion + '.0', '2.13.0')) {
error('glibc version ' + glibcVersion + ' requires manual installation - please see http://sharp.dimens.io/en/stable/install/'); error('glibc version ' + glibcVersion + ' requires manual installation - please see http://sharp.dimens.io/en/stable/install/');

View File

@@ -140,6 +140,8 @@ Use these TIFF options for output image.
- `options.force` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** force TIFF output, otherwise attempt to use input format (optional, default `true`) - `options.force` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** force TIFF output, otherwise attempt to use input format (optional, default `true`)
- `options.compression` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** compression options: lzw, deflate, jpeg (optional, default `'jpeg'`) - `options.compression` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** compression options: lzw, deflate, jpeg (optional, default `'jpeg'`)
- `options.predictor` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** compression predictor options: none, horizontal, float (optional, default `'none'`) - `options.predictor` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** compression predictor options: none, horizontal, float (optional, default `'none'`)
- `options.xres` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** horizontal resolution in pixels/mm (optional, default `1.0`)
- `options.yres` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** vertical resolution in pixels/mm (optional, default `1.0`)
- `options.squash` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** squash 8-bit images down to 1 bit (optional, default `false`) - `options.squash` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** squash 8-bit images down to 1 bit (optional, default `false`)

View File

@@ -4,6 +4,29 @@
Requires libvips v8.5.5. Requires libvips v8.5.5.
#### v0.18.2 - 1<sup>st</sup> July 2017
* Expose libvips' xres and yres properties for TIFF output.
[#828](https://github.com/lovell/sharp/pull/828)
[@YvesBos](https://github.com/YvesBos)
* Ensure flip and flop operations work with auto-rotate.
[#837](https://github.com/lovell/sharp/issues/837)
[@rexxars](https://github.com/rexxars)
* Allow binary download URL override via SHARP_DIST_BASE_URL env variable.
[#841](https://github.com/lovell/sharp/issues/841)
* Add support for Solus Linux.
[#857](https://github.com/lovell/sharp/pull/857)
[@ekremkaraca](https://github.com/ekremkaraca)
#### v0.18.1 - 30<sup>th</sup> May 2017
* Remove regression from #781 that could cause incorrect shrink calculation.
[#831](https://github.com/lovell/sharp/issues/831)
[@suprMax](https://github.com/suprMax)
#### v0.18.0 - 30<sup>th</sup> May 2017 #### v0.18.0 - 30<sup>th</sup> May 2017
* Remove the previously-deprecated output format "option" functions: * Remove the previously-deprecated output format "option" functions:

View File

@@ -10,7 +10,7 @@ yarn add sharp
### Prerequisites ### Prerequisites
* Node v4+ * Node v4.5.0+
* C++11 compatible compiler such as gcc 4.8+, clang 3.0+ or MSVC 2013+ * C++11 compatible compiler such as gcc 4.8+, clang 3.0+ or MSVC 2013+
* [node-gyp](https://github.com/TooTallNate/node-gyp#installation) and its dependencies (includes Python) * [node-gyp](https://github.com/TooTallNate/node-gyp#installation) and its dependencies (includes Python)
@@ -32,6 +32,7 @@ Most recent Linux-based operating systems with glibc running on x64 and ARMv6+ C
* Archlinux * Archlinux
* Raspbian Jessie * Raspbian Jessie
* Amazon Linux 2016.03, 2016.09 * Amazon Linux 2016.03, 2016.09
* Solus
To use a globally-installed version of libvips instead of the provided binaries, To use a globally-installed version of libvips instead of the provided binaries,
make sure it is at least the version listed under `config.libvips` in the `package.json` file make sure it is at least the version listed under `config.libvips` in the `package.json` file
@@ -48,8 +49,17 @@ it is recommended to install a system-wide installation of libvips from source:
https://github.com/jcupitt/libvips#building-libvips-from-a-source-tarball https://github.com/jcupitt/libvips#building-libvips-from-a-source-tarball
For Linux-based operating systems such as Alpine that use musl libc, #### Alpine Linux
the smaller stack size means libvips' cache should be disabled
libvips is available in the
[testing repository](https://pkgs.alpinelinux.org/packages?name=vips-dev):
```sh
apk add vips-dev --update-cache --repository https://dl-3.alpinelinux.org/alpine/edge/testing/
```
The smaller stack size of musl libc means
libvips may need to be used without a cache
via `sharp.cache(false)` to avoid a stack overflow. via `sharp.cache(false)` to avoid a stack overflow.
### Mac OS ### Mac OS
@@ -183,16 +193,27 @@ configuration file to prevent the use of coders known to be vulnerable.
Set the `MAGICK_CONFIGURE_PATH` environment variable Set the `MAGICK_CONFIGURE_PATH` environment variable
to the directory containing the `policy.xml` file. to the directory containing the `policy.xml` file.
### Licences ### Pre-compiled libvips binaries
If a global installation of libvips that meets the If a global installation of libvips that meets the
minimum version requirement cannot be found, minimum version requirement cannot be found,
this module will download a pre-compiled bundle of libvips this module will attempt to download a pre-compiled bundle of libvips
and its dependencies on Linux and Windows machines. and its dependencies on Linux and Windows machines.
Should you need to manually download and inspect these files, Should you need to manually download and inspect these files,
you can do so via https://dl.bintray.com/lovell/sharp/ you can do so via https://dl.bintray.com/lovell/sharp/
Should you wish to install these from your own location,
set the `SHARP_DIST_BASE_URL` environment variable, e.g.
```sh
SHARP_DIST_BASE_URL="https://hostname/path/" npm install sharp
```
to use `https://hostname/path/libvips-x.y.z-platform.tar.gz`.
### Licences
This module is licensed under the terms of the This module is licensed under the terms of the
[Apache 2.0 Licence](https://github.com/lovell/sharp/blob/master/LICENSE). [Apache 2.0 Licence](https://github.com/lovell/sharp/blob/master/LICENSE).

View File

@@ -180,6 +180,8 @@ const Sharp = function (input, options) {
tiffCompression: 'jpeg', tiffCompression: 'jpeg',
tiffPredictor: 'none', tiffPredictor: 'none',
tiffSquash: false, tiffSquash: false,
tiffXres: 1.0,
tiffYres: 1.0,
tileSize: 256, tileSize: 256,
tileOverlap: 0, tileOverlap: 0,
// Function to notify of libvips warnings // Function to notify of libvips warnings

View File

@@ -214,6 +214,8 @@ function webp (options) {
* @param {Boolean} [options.force=true] - force TIFF output, otherwise attempt to use input format * @param {Boolean} [options.force=true] - force TIFF output, otherwise attempt to use input format
* @param {Boolean} [options.compression='jpeg'] - compression options: lzw, deflate, jpeg * @param {Boolean} [options.compression='jpeg'] - compression options: lzw, deflate, jpeg
* @param {Boolean} [options.predictor='none'] - compression predictor options: none, horizontal, float * @param {Boolean} [options.predictor='none'] - compression predictor options: none, horizontal, float
* @param {Number} [options.xres=1.0] - horizontal resolution in pixels/mm
* @param {Number} [options.yres=1.0] - vertical resolution in pixels/mm
* @param {Boolean} [options.squash=false] - squash 8-bit images down to 1 bit * @param {Boolean} [options.squash=false] - squash 8-bit images down to 1 bit
* @returns {Sharp} * @returns {Sharp}
* @throws {Error} Invalid options * @throws {Error} Invalid options
@@ -233,6 +235,21 @@ function tiff (options) {
throw new Error('Invalid Value for squash ' + options.squash + ' Only Boolean Values allowed for options.squash.'); throw new Error('Invalid Value for squash ' + options.squash + ' Only Boolean Values allowed for options.squash.');
} }
} }
// resolution
if (is.object(options) && is.defined(options.xres)) {
if (is.number(options.xres)) {
this.options.tiffXres = options.xres;
} else {
throw new Error('Invalid Value for xres ' + options.xres + ' Only numeric values allowed for options.xres');
}
}
if (is.object(options) && is.defined(options.yres)) {
if (is.number(options.yres)) {
this.options.tiffYres = options.yres;
} else {
throw new Error('Invalid Value for yres ' + options.yres + ' Only numeric values allowed for options.yres');
}
}
// compression // compression
if (is.defined(options) && is.defined(options.compression)) { if (is.defined(options) && is.defined(options.compression)) {
if (is.string(options.compression) && is.inArray(options.compression, ['lzw', 'deflate', 'jpeg', 'none'])) { if (is.string(options.compression) && is.inArray(options.compression, ['lzw', 'deflate', 'jpeg', 'none'])) {

View File

@@ -1,7 +1,7 @@
{ {
"name": "sharp", "name": "sharp",
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images", "description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images",
"version": "0.18.0", "version": "0.18.2",
"author": "Lovell Fuller <npm@lovell.info>", "author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp", "homepage": "https://github.com/lovell/sharp",
"contributors": [ "contributors": [
@@ -68,20 +68,20 @@
], ],
"dependencies": { "dependencies": {
"caw": "^2.0.0", "caw": "^2.0.0",
"color": "^1.0.3", "color": "^2.0.0",
"got": "^7.0.0", "got": "^7.1.0",
"nan": "^2.6.2", "nan": "^2.6.2",
"semver": "^5.3.0", "semver": "^5.3.0",
"tar": "^3.1.3" "tar": "^3.1.5"
}, },
"devDependencies": { "devDependencies": {
"async": "^2.4.1", "async": "^2.5.0",
"cc": "^1.0.1", "cc": "^1.0.1",
"documentation": "^4.0.0-rc.1", "documentation": "^4.0.0-rc.1",
"exif-reader": "^1.0.2", "exif-reader": "^1.0.2",
"icc": "^1.0.0", "icc": "^1.0.0",
"mocha": "^3.4.2", "mocha": "^3.4.2",
"nyc": "^10.3.2", "nyc": "^11.0.3",
"rimraf": "^2.6.1", "rimraf": "^2.6.1",
"semistandard": "^11.0.0", "semistandard": "^11.0.0",
"unzip": "^0.1.11" "unzip": "^0.1.11"
@@ -91,7 +91,7 @@
"libvips": "8.5.5" "libvips": "8.5.5"
}, },
"engines": { "engines": {
"node": ">=4" "node": ">=4.5.0"
}, },
"semistandard": { "semistandard": {
"env": [ "env": [

View File

@@ -438,9 +438,11 @@ namespace sharp {
// Southeast // Southeast
left = inWidth - outWidth; left = inWidth - outWidth;
top = inHeight - outHeight; top = inHeight - outHeight;
break;
case 7: case 7:
// Southwest // Southwest
top = inHeight - outHeight; top = inHeight - outHeight;
break;
case 8: case 8:
// Northwest // Northwest
break; break;

View File

@@ -83,8 +83,11 @@ class PipelineWorker : public Nan::AsyncWorker {
VipsAngle rotation; VipsAngle rotation;
if (baton->useExifOrientation) { if (baton->useExifOrientation) {
// Rotate and flip image according to Exif orientation // Rotate and flip image according to Exif orientation
// (ignore the requested rotation and flip) bool flip;
std::tie(rotation, baton->flip, baton->flop) = CalculateExifRotationAndFlip(sharp::ExifOrientation(image)); bool flop;
std::tie(rotation, flip, flop) = CalculateExifRotationAndFlip(sharp::ExifOrientation(image));
baton->flip = baton->flip || flip;
baton->flop = baton->flop || flop;
} else { } else {
rotation = CalculateAngleRotation(baton->angle); rotation = CalculateAngleRotation(baton->angle);
} }
@@ -288,11 +291,11 @@ class PipelineWorker : public Nan::AsyncWorker {
} }
} }
// Help ensure a final kernel-based reduction to prevent shrink aliasing // Help ensure a final kernel-based reduction to prevent shrink aliasing
if ((xshrink > 1 || yshrink > 1) && (xresidual == 1.0 || yresidual == 1.0)) { if (xshrink > 1 && yshrink > 1 && (xresidual == 1.0 || yresidual == 1.0)) {
xshrink = xshrink / 2; xshrink = xshrink / 2;
yshrink = yshrink / 2; yshrink = yshrink / 2;
xresidual = xresidual / 2.0; xresidual = static_cast<double>(xshrink) / xfactor;
yresidual = yresidual / 2.0; yresidual = static_cast<double>(yshrink) / yfactor;
} }
// Ensure we're using a device-independent colour space // Ensure we're using a device-independent colour space
@@ -808,7 +811,9 @@ class PipelineWorker : public Nan::AsyncWorker {
->set("Q", baton->tiffQuality) ->set("Q", baton->tiffQuality)
->set("squash", baton->tiffSquash) ->set("squash", baton->tiffSquash)
->set("compression", baton->tiffCompression) ->set("compression", baton->tiffCompression)
->set("predictor", baton->tiffPredictor))); ->set("predictor", baton->tiffPredictor)
->set("xres", baton->tiffXres)
->set("yres", baton->tiffYres)));
baton->bufferOut = static_cast<char*>(area->data); baton->bufferOut = static_cast<char*>(area->data);
baton->bufferOutLength = area->length; baton->bufferOutLength = area->length;
area->free_fn = nullptr; area->free_fn = nullptr;
@@ -904,7 +909,9 @@ class PipelineWorker : public Nan::AsyncWorker {
->set("Q", baton->tiffQuality) ->set("Q", baton->tiffQuality)
->set("squash", baton->tiffSquash) ->set("squash", baton->tiffSquash)
->set("compression", baton->tiffCompression) ->set("compression", baton->tiffCompression)
->set("predictor", baton->tiffPredictor)); ->set("predictor", baton->tiffPredictor)
->set("xres", baton->tiffXres)
->set("yres", baton->tiffYres));
baton->formatOut = "tiff"; baton->formatOut = "tiff";
baton->channels = std::min(baton->channels, 3); baton->channels = std::min(baton->channels, 3);
} else if (baton->formatOut == "dz" || isDz || isDzZip) { } else if (baton->formatOut == "dz" || isDz || isDzZip) {
@@ -1277,6 +1284,8 @@ NAN_METHOD(pipeline) {
baton->webpNearLossless = AttrTo<bool>(options, "webpNearLossless"); baton->webpNearLossless = AttrTo<bool>(options, "webpNearLossless");
baton->tiffQuality = AttrTo<uint32_t>(options, "tiffQuality"); baton->tiffQuality = AttrTo<uint32_t>(options, "tiffQuality");
baton->tiffSquash = AttrTo<bool>(options, "tiffSquash"); baton->tiffSquash = AttrTo<bool>(options, "tiffSquash");
baton->tiffXres = AttrTo<double>(options, "tiffXres");
baton->tiffYres = AttrTo<double>(options, "tiffYres");
// tiff compression options // tiff compression options
baton->tiffCompression = static_cast<VipsForeignTiffCompression>( baton->tiffCompression = static_cast<VipsForeignTiffCompression>(
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_TIFF_COMPRESSION, vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_TIFF_COMPRESSION,

View File

@@ -109,6 +109,8 @@ struct PipelineBaton {
VipsForeignTiffCompression tiffCompression; VipsForeignTiffCompression tiffCompression;
VipsForeignTiffPredictor tiffPredictor; VipsForeignTiffPredictor tiffPredictor;
bool tiffSquash; bool tiffSquash;
double tiffXres;
double tiffYres;
std::string err; std::string err;
bool withMetadata; bool withMetadata;
int withMetadataOrientation; int withMetadataOrientation;
@@ -182,6 +184,8 @@ struct PipelineBaton {
tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG), tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_NONE), tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_NONE),
tiffSquash(false), tiffSquash(false),
tiffXres(1.0),
tiffYres(1.0),
withMetadata(false), withMetadata(false),
withMetadataOrientation(-1), withMetadataOrientation(-1),
convKernelWidth(0), convKernelWidth(0),

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -933,6 +933,53 @@ describe('Input/output', function () {
}); });
}); });
it('TIFF setting xres and yres on file', function (done) {
const res = 1000.0; // inputTiff has a dpi of 300 (res*2.54)
sharp(fixtures.inputTiff)
.tiff({
xres: (res),
yres: (res)
})
.toFile(fixtures.outputTiff, (err, info) => {
if (err) throw err;
assert.strictEqual('tiff', info.format);
sharp(fixtures.outputTiff).metadata(function (err, metadata) {
if (err) throw err;
assert.strictEqual(metadata.density, res * 2.54); // convert to dpi
fs.unlink(fixtures.outputTiff, done);
});
});
});
it('TIFF setting xres and yres on buffer', function (done) {
const res = 1000.0; // inputTiff has a dpi of 300 (res*2.54)
sharp(fixtures.inputTiff)
.tiff({
xres: (res),
yres: (res)
})
.toBuffer(function (err, data, info) {
if (err) throw err;
sharp(data).metadata(function (err, metadata) {
if (err) throw err;
assert.strictEqual(metadata.density, res * 2.54); // convert to dpi
done();
});
});
});
it('TIFF invalid xres value should throw an error', function () {
assert.throws(function () {
sharp().tiff({ xres: '1000.0' });
});
});
it('TIFF invalid yres value should throw an error', function () {
assert.throws(function () {
sharp().tiff({ yres: '1000.0' });
});
});
it('TIFF lzw compression with horizontal predictor shrinks test file', function (done) { it('TIFF lzw compression with horizontal predictor shrinks test file', function (done) {
const startSize = fs.statSync(fixtures.inputTiffUncompressed).size; const startSize = fs.statSync(fixtures.inputTiffUncompressed).size;
sharp(fixtures.inputTiffUncompressed) sharp(fixtures.inputTiffUncompressed)

View File

@@ -412,4 +412,40 @@ describe('Resize dimensions', function () {
sharp().resize(32, 24, { centreSampling: 1 }); sharp().resize(32, 24, { centreSampling: 1 });
}); });
}); });
it('Dimensions that result in differing even shrinks on each axis', function (done) {
sharp(fixtures.inputJpg)
.resize(645, 399)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(645, info.width);
assert.strictEqual(399, info.height);
sharp(data)
.resize(150, 100)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(150, info.width);
assert.strictEqual(100, info.height);
fixtures.assertSimilar(fixtures.expected('resize-diff-shrink-even.jpg'), data, done);
});
});
});
it('Dimensions that result in differing odd shrinks on each axis', function (done) {
return sharp(fixtures.inputJpg)
.resize(600, 399)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(600, info.width);
assert.strictEqual(399, info.height);
sharp(data)
.resize(200)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(200, info.width);
assert.strictEqual(133, info.height);
fixtures.assertSimilar(fixtures.expected('resize-diff-shrink-odd.jpg'), data, done);
});
});
});
}); });

View File

@@ -253,4 +253,32 @@ describe('Rotation', function () {
fixtures.assertSimilar(fixtures.inputJpg, data, done); fixtures.assertSimilar(fixtures.inputJpg, data, done);
}); });
}); });
it('Auto-rotate and flip', function (done) {
sharp(fixtures.inputJpgWithExif)
.rotate()
.flip()
.resize(320)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
assert.strictEqual(320, info.width);
assert.strictEqual(240, info.height);
fixtures.assertSimilar(fixtures.expected('rotate-and-flip.jpg'), data, done);
});
});
it('Auto-rotate and flop', function (done) {
sharp(fixtures.inputJpgWithExif)
.rotate()
.flop()
.resize(320)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
assert.strictEqual(320, info.width);
assert.strictEqual(240, info.height);
fixtures.assertSimilar(fixtures.expected('rotate-and-flop.jpg'), data, done);
});
});
}); });