mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 18:40:16 +02:00
Add features from libvips 7.40+
Load TIFF from Buffer/Stream Interlaced PNG output no longer needs tilecache Option to disable PNG adaptive row filtering
This commit is contained in:
parent
740838b47c
commit
7537adf399
12
README.md
12
README.md
@ -29,7 +29,7 @@ This module is powered by the blazingly fast [libvips](https://github.com/jcupit
|
|||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
* Node.js v0.10+
|
* Node.js v0.10+
|
||||||
* [libvips](https://github.com/jcupitt/libvips) v7.38.5+
|
* [libvips](https://github.com/jcupitt/libvips) v7.38.5+ (7.40.9+ recommended)
|
||||||
|
|
||||||
To install the latest version of libvips on the following Operating Systems:
|
To install the latest version of libvips on the following Operating Systems:
|
||||||
|
|
||||||
@ -214,12 +214,12 @@ sharp(inputBuffer)
|
|||||||
|
|
||||||
Constructor to which further methods are chained. `input`, if present, can be one of:
|
Constructor to which further methods are chained. `input`, if present, can be one of:
|
||||||
|
|
||||||
* Buffer containing JPEG, PNG or WebP image data, or
|
* Buffer containing JPEG, PNG, WebP or TIFF (libvips 7.40.0+) image data, or
|
||||||
* String containing the filename of an image, with most major formats supported.
|
* String containing the filename of an image, with most major formats supported.
|
||||||
|
|
||||||
The object returned implements the [stream.Duplex](http://nodejs.org/api/stream.html#stream_class_stream_duplex) class.
|
The object returned implements the [stream.Duplex](http://nodejs.org/api/stream.html#stream_class_stream_duplex) class.
|
||||||
|
|
||||||
JPEG, PNG or WebP format image data can be streamed into the object when `input` is not provided.
|
JPEG, PNG, WebP or TIFF (libvips 7.40.0+) format image data can be streamed into the object when `input` is not provided.
|
||||||
|
|
||||||
JPEG, PNG or WebP format image data can be streamed out from this object.
|
JPEG, PNG or WebP format image data can be streamed out from this object.
|
||||||
|
|
||||||
@ -388,6 +388,12 @@ An advanced setting for the _zlib_ compression level of the lossless PNG output
|
|||||||
|
|
||||||
`compressionLevel` is a Number between 0 and 9.
|
`compressionLevel` is a Number between 0 and 9.
|
||||||
|
|
||||||
|
#### withoutAdaptiveFiltering()
|
||||||
|
|
||||||
|
_Requires libvips 7.41.0+_
|
||||||
|
|
||||||
|
An advanced and experimental PNG output setting to disable adaptive row filtering.
|
||||||
|
|
||||||
### Output methods
|
### Output methods
|
||||||
|
|
||||||
#### toFile(filename, [callback])
|
#### toFile(filename, [callback])
|
||||||
|
43
index.js
43
index.js
@ -4,10 +4,12 @@ var path = require('path');
|
|||||||
var util = require('util');
|
var util = require('util');
|
||||||
var stream = require('stream');
|
var stream = require('stream');
|
||||||
|
|
||||||
|
var semver = require('semver');
|
||||||
var color = require('color');
|
var color = require('color');
|
||||||
var BluebirdPromise = require('bluebird');
|
var BluebirdPromise = require('bluebird');
|
||||||
|
|
||||||
var sharp = require('./build/Release/sharp');
|
var sharp = require('./build/Release/sharp');
|
||||||
|
var libvipsVersion = sharp.libvipsVersion();
|
||||||
|
|
||||||
var Sharp = function(input) {
|
var Sharp = function(input) {
|
||||||
if (!(this instanceof Sharp)) {
|
if (!(this instanceof Sharp)) {
|
||||||
@ -49,6 +51,7 @@ var Sharp = function(input) {
|
|||||||
progressive: false,
|
progressive: false,
|
||||||
quality: 80,
|
quality: 80,
|
||||||
compressionLevel: 6,
|
compressionLevel: 6,
|
||||||
|
withoutAdaptiveFiltering: false,
|
||||||
streamOut: false,
|
streamOut: false,
|
||||||
withMetadata: false
|
withMetadata: false
|
||||||
};
|
};
|
||||||
@ -58,14 +61,22 @@ var Sharp = function(input) {
|
|||||||
} else if (typeof input === 'object' && input instanceof Buffer) {
|
} else if (typeof input === 'object' && input instanceof Buffer) {
|
||||||
// input=buffer
|
// input=buffer
|
||||||
if (
|
if (
|
||||||
(input.length > 1) &&
|
(input.length > 3) &&
|
||||||
(input[0] === 0xff && input[1] === 0xd8) || // JPEG
|
// JPEG
|
||||||
(input[0] === 0x89 && input[1] === 0x50) || // PNG
|
(input[0] === 0xFF && input[1] === 0xD8) ||
|
||||||
(input[0] === 0x52 && input[1] === 0x49) // WebP
|
// PNG
|
||||||
|
(input[0] === 0x89 && input[1] === 0x50) ||
|
||||||
|
// WebP
|
||||||
|
(input[0] === 0x52 && input[1] === 0x49) ||
|
||||||
|
// TIFF - requires libvips 7.40.0+
|
||||||
|
(semver.gte(libvipsVersion, '7.40.0') && (
|
||||||
|
(input[0] === 0x4D && input[1] === 0x4D && input[2] === 0x00 && (input[3] === 0x2A || input[3] === 0x2B)) ||
|
||||||
|
(input[0] === 0x49 && input[1] === 0x49 && (input[2] === 0x2A || input[2] === 0x2B) && input[3] === 0x00)
|
||||||
|
))
|
||||||
) {
|
) {
|
||||||
this.options.bufferIn = input;
|
this.options.bufferIn = input;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Buffer contains an unsupported image format. JPEG, PNG and WebP are currently supported.');
|
throw new Error('Buffer contains an unsupported image format. JPEG, PNG, WebP and TIFF are currently supported.');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// input=stream
|
// input=stream
|
||||||
@ -269,6 +280,9 @@ Sharp.prototype.quality = function(quality) {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
zlib compression level for PNG output
|
||||||
|
*/
|
||||||
Sharp.prototype.compressionLevel = function(compressionLevel) {
|
Sharp.prototype.compressionLevel = function(compressionLevel) {
|
||||||
if (!Number.isNaN(compressionLevel) && compressionLevel >= 0 && compressionLevel <= 9) {
|
if (!Number.isNaN(compressionLevel) && compressionLevel >= 0 && compressionLevel <= 9) {
|
||||||
this.options.compressionLevel = compressionLevel;
|
this.options.compressionLevel = compressionLevel;
|
||||||
@ -278,6 +292,18 @@ Sharp.prototype.compressionLevel = function(compressionLevel) {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Disable the use of adaptive row filtering for PNG output - requires libvips 7.41.0+
|
||||||
|
*/
|
||||||
|
Sharp.prototype.withoutAdaptiveFiltering = function(withoutAdaptiveFiltering) {
|
||||||
|
if (semver.gte(libvipsVersion, '7.41.0')) {
|
||||||
|
this.options.withoutAdaptiveFiltering = (typeof withoutAdaptiveFiltering === 'boolean') ? withoutAdaptiveFiltering : true;
|
||||||
|
} else {
|
||||||
|
console.error('withoutAdaptiveFiltering requires libvips 7.41.0+');
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
Sharp.prototype.withMetadata = function(withMetadata) {
|
Sharp.prototype.withMetadata = function(withMetadata) {
|
||||||
this.options.withMetadata = (typeof withMetadata === 'boolean') ? withMetadata : true;
|
this.options.withMetadata = (typeof withMetadata === 'boolean') ? withMetadata : true;
|
||||||
return this;
|
return this;
|
||||||
@ -506,3 +532,10 @@ module.exports.concurrency = function(concurrency) {
|
|||||||
module.exports.counters = function() {
|
module.exports.counters = function() {
|
||||||
return sharp.counters();
|
return sharp.counters();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get the version of the libvips library
|
||||||
|
*/
|
||||||
|
module.exports.libvipsVersion = function() {
|
||||||
|
return libvipsVersion;
|
||||||
|
};
|
||||||
|
@ -41,9 +41,10 @@
|
|||||||
"stream"
|
"stream"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bluebird": "^2.3.10",
|
"bluebird": "^2.3.11",
|
||||||
"color": "^0.7.1",
|
"color": "^0.7.1",
|
||||||
"nan": "^1.4.0"
|
"nan": "^1.4.0",
|
||||||
|
"semver": "^4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "^2.0.1",
|
"mocha": "^2.0.1",
|
||||||
|
@ -27,12 +27,25 @@ bool is_tiff(std::string const &str) {
|
|||||||
return ends_with(str, ".tif") || ends_with(str, ".tiff") || ends_with(str, ".TIF") || ends_with(str, ".TIFF");
|
return ends_with(str, ".tif") || ends_with(str, ".tiff") || ends_with(str, ".TIF") || ends_with(str, ".TIFF");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Buffer content checkers
|
||||||
|
|
||||||
|
#if (VIPS_MAJOR_VERSION >= 7 && VIPS_MINOR_VERSION >= 40)
|
||||||
|
static bool buffer_is_tiff(char *buffer, size_t len) {
|
||||||
|
return (
|
||||||
|
len >= 4 && (
|
||||||
|
(buffer[0] == 'M' && buffer[1] == 'M' && buffer[2] == '\0' && (buffer[3] == '*' || buffer[3] == '+')) ||
|
||||||
|
(buffer[0] == 'I' && buffer[1] == 'I' && (buffer[2] == '*' || buffer[2] == '+') && buffer[3] == '\0')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned char const MARKER_JPEG[] = {0xff, 0xd8};
|
unsigned char const MARKER_JPEG[] = {0xff, 0xd8};
|
||||||
unsigned char const MARKER_PNG[] = {0x89, 0x50};
|
unsigned char const MARKER_PNG[] = {0x89, 0x50};
|
||||||
unsigned char const MARKER_WEBP[] = {0x52, 0x49};
|
unsigned char const MARKER_WEBP[] = {0x52, 0x49};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initialise a VipsImage from a buffer. Supports JPEG, PNG and WebP.
|
Initialise a VipsImage from a buffer. Supports JPEG, PNG, WebP and TIFF.
|
||||||
Returns the ImageType detected, if any.
|
Returns the ImageType detected, if any.
|
||||||
*/
|
*/
|
||||||
ImageType
|
ImageType
|
||||||
@ -42,14 +55,20 @@ sharp_init_image_from_buffer(VipsImage **image, void *buffer, size_t const lengt
|
|||||||
if (!vips_jpegload_buffer(buffer, length, image, "access", access, NULL)) {
|
if (!vips_jpegload_buffer(buffer, length, image, "access", access, NULL)) {
|
||||||
imageType = JPEG;
|
imageType = JPEG;
|
||||||
}
|
}
|
||||||
} else if(memcmp(MARKER_PNG, buffer, 2) == 0) {
|
} else if (memcmp(MARKER_PNG, buffer, 2) == 0) {
|
||||||
if (!vips_pngload_buffer(buffer, length, image, "access", access, NULL)) {
|
if (!vips_pngload_buffer(buffer, length, image, "access", access, NULL)) {
|
||||||
imageType = PNG;
|
imageType = PNG;
|
||||||
}
|
}
|
||||||
} else if(memcmp(MARKER_WEBP, buffer, 2) == 0) {
|
} else if (memcmp(MARKER_WEBP, buffer, 2) == 0) {
|
||||||
if (!vips_webpload_buffer(buffer, length, image, "access", access, NULL)) {
|
if (!vips_webpload_buffer(buffer, length, image, "access", access, NULL)) {
|
||||||
imageType = WEBP;
|
imageType = WEBP;
|
||||||
}
|
}
|
||||||
|
#if (VIPS_MAJOR_VERSION >= 7 && VIPS_MINOR_VERSION >= 40)
|
||||||
|
} else if (buffer_is_tiff(static_cast<char*>(buffer), length)) {
|
||||||
|
if (!vips_tiffload_buffer(buffer, length, image, "access", access, NULL)) {
|
||||||
|
imageType = TIFF;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return imageType;
|
return imageType;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ struct ResizeBaton {
|
|||||||
VipsAccess accessMethod;
|
VipsAccess accessMethod;
|
||||||
int quality;
|
int quality;
|
||||||
int compressionLevel;
|
int compressionLevel;
|
||||||
|
bool withoutAdaptiveFiltering;
|
||||||
std::string err;
|
std::string err;
|
||||||
bool withMetadata;
|
bool withMetadata;
|
||||||
|
|
||||||
@ -517,7 +518,8 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
image = colourspaced;
|
image = colourspaced;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate image tile cache when interlace output is required
|
#if !(VIPS_MAJOR_VERSION >= 7 && VIPS_MINOR_VERSION >= 40 && VIPS_MINOR_VERSION >= 5)
|
||||||
|
// Generate image tile cache when interlace output is required - no longer required as of libvips 7.40.5+
|
||||||
if (baton->progressive) {
|
if (baton->progressive) {
|
||||||
VipsImage *cached = vips_image_new();
|
VipsImage *cached = vips_image_new();
|
||||||
vips_object_local(hook, cached);
|
vips_object_local(hook, cached);
|
||||||
@ -527,6 +529,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
g_object_unref(image);
|
g_object_unref(image);
|
||||||
image = cached;
|
image = cached;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
if (baton->output == "__jpeg" || (baton->output == "__input" && inputImageType == JPEG)) {
|
if (baton->output == "__jpeg" || (baton->output == "__input" && inputImageType == JPEG)) {
|
||||||
@ -537,11 +540,21 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
}
|
}
|
||||||
baton->outputFormat = "jpeg";
|
baton->outputFormat = "jpeg";
|
||||||
} else if (baton->output == "__png" || (baton->output == "__input" && inputImageType == PNG)) {
|
} else if (baton->output == "__png" || (baton->output == "__input" && inputImageType == PNG)) {
|
||||||
|
#if (VIPS_MAJOR_VERSION >= 7 && VIPS_MINOR_VERSION >= 41)
|
||||||
|
// Select PNG row filter
|
||||||
|
int filter = baton->withoutAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_NONE : VIPS_FOREIGN_PNG_FILTER_ALL;
|
||||||
|
// Write PNG to buffer
|
||||||
|
if (vips_pngsave_buffer(image, &baton->bufferOut, &baton->bufferOutLength, "strip", !baton->withMetadata,
|
||||||
|
"compression", baton->compressionLevel, "interlace", baton->progressive, "filter", filter, NULL)) {
|
||||||
|
return Error(baton, hook);
|
||||||
|
}
|
||||||
|
#else
|
||||||
// Write PNG to buffer
|
// Write PNG to buffer
|
||||||
if (vips_pngsave_buffer(image, &baton->bufferOut, &baton->bufferOutLength, "strip", !baton->withMetadata,
|
if (vips_pngsave_buffer(image, &baton->bufferOut, &baton->bufferOutLength, "strip", !baton->withMetadata,
|
||||||
"compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
"compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error(baton, hook);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
baton->outputFormat = "png";
|
baton->outputFormat = "png";
|
||||||
} else if (baton->output == "__webp" || (baton->output == "__input" && inputImageType == WEBP)) {
|
} else if (baton->output == "__webp" || (baton->output == "__input" && inputImageType == WEBP)) {
|
||||||
// Write WEBP to buffer
|
// Write WEBP to buffer
|
||||||
@ -564,11 +577,21 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
}
|
}
|
||||||
baton->outputFormat = "jpeg";
|
baton->outputFormat = "jpeg";
|
||||||
} else if (output_png || (match_input && inputImageType == PNG)) {
|
} else if (output_png || (match_input && inputImageType == PNG)) {
|
||||||
|
#if (VIPS_MAJOR_VERSION >= 7 && VIPS_MINOR_VERSION >= 41)
|
||||||
|
// Select PNG row filter
|
||||||
|
int filter = baton->withoutAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_NONE : VIPS_FOREIGN_PNG_FILTER_ALL;
|
||||||
|
// Write PNG to file
|
||||||
|
if (vips_pngsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
||||||
|
"compression", baton->compressionLevel, "interlace", baton->progressive, "filter", filter, NULL)) {
|
||||||
|
return Error(baton, hook);
|
||||||
|
}
|
||||||
|
#else
|
||||||
// Write PNG to file
|
// Write PNG to file
|
||||||
if (vips_pngsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
if (vips_pngsave(image, baton->output.c_str(), "strip", !baton->withMetadata,
|
||||||
"compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
"compression", baton->compressionLevel, "interlace", baton->progressive, NULL)) {
|
||||||
return Error(baton, hook);
|
return Error(baton, hook);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
baton->outputFormat = "png";
|
baton->outputFormat = "png";
|
||||||
} else if (output_webp || (match_input && inputImageType == WEBP)) {
|
} else if (output_webp || (match_input && inputImageType == WEBP)) {
|
||||||
// Write WEBP to file
|
// Write WEBP to file
|
||||||
@ -798,6 +821,7 @@ NAN_METHOD(resize) {
|
|||||||
baton->progressive = options->Get(NanNew<String>("progressive"))->BooleanValue();
|
baton->progressive = options->Get(NanNew<String>("progressive"))->BooleanValue();
|
||||||
baton->quality = options->Get(NanNew<String>("quality"))->Int32Value();
|
baton->quality = options->Get(NanNew<String>("quality"))->Int32Value();
|
||||||
baton->compressionLevel = options->Get(NanNew<String>("compressionLevel"))->Int32Value();
|
baton->compressionLevel = options->Get(NanNew<String>("compressionLevel"))->Int32Value();
|
||||||
|
baton->withoutAdaptiveFiltering = options->Get(NanNew<String>("withoutAdaptiveFiltering"))->BooleanValue();
|
||||||
baton->withMetadata = options->Get(NanNew<String>("withMetadata"))->BooleanValue();
|
baton->withMetadata = options->Get(NanNew<String>("withMetadata"))->BooleanValue();
|
||||||
// Output filename or __format for Buffer
|
// Output filename or __format for Buffer
|
||||||
baton->output = *String::Utf8Value(options->Get(NanNew<String>("output"))->ToString());
|
baton->output = *String::Utf8Value(options->Get(NanNew<String>("output"))->ToString());
|
||||||
|
@ -33,6 +33,7 @@ extern "C" void init(Handle<Object> target) {
|
|||||||
NODE_SET_METHOD(target, "cache", cache);
|
NODE_SET_METHOD(target, "cache", cache);
|
||||||
NODE_SET_METHOD(target, "concurrency", concurrency);
|
NODE_SET_METHOD(target, "concurrency", concurrency);
|
||||||
NODE_SET_METHOD(target, "counters", counters);
|
NODE_SET_METHOD(target, "counters", counters);
|
||||||
|
NODE_SET_METHOD(target, "libvipsVersion", libvipsVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
NODE_MODULE(sharp, init)
|
NODE_MODULE(sharp, init)
|
||||||
|
@ -62,3 +62,13 @@ NAN_METHOD(counters) {
|
|||||||
counters->Set(NanNew<String>("process"), NanNew<Number>(counter_process));
|
counters->Set(NanNew<String>("process"), NanNew<Number>(counter_process));
|
||||||
NanReturnValue(counters);
|
NanReturnValue(counters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get libvips version
|
||||||
|
*/
|
||||||
|
NAN_METHOD(libvipsVersion) {
|
||||||
|
NanScope();
|
||||||
|
char version[9];
|
||||||
|
snprintf(version, 9, "%d.%d.%d", vips_version(0), vips_version(1), vips_version(2));
|
||||||
|
NanReturnValue(NanNew<String>(version));
|
||||||
|
}
|
||||||
|
@ -6,5 +6,6 @@
|
|||||||
NAN_METHOD(cache);
|
NAN_METHOD(cache);
|
||||||
NAN_METHOD(concurrency);
|
NAN_METHOD(concurrency);
|
||||||
NAN_METHOD(counters);
|
NAN_METHOD(counters);
|
||||||
|
NAN_METHOD(libvipsVersion);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,9 +9,10 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"imagemagick": "^0.1.3",
|
"imagemagick": "^0.1.3",
|
||||||
"imagemagick-native": "^1.4.0",
|
"imagemagick-native": "^1.5.0",
|
||||||
"gm": "^1.16.0",
|
"gm": "^1.17.0",
|
||||||
"async": "^0.9.0",
|
"async": "^0.9.0",
|
||||||
|
"semver": "^4.1.0",
|
||||||
"benchmark": "^1.0.0"
|
"benchmark": "^1.0.0"
|
||||||
},
|
},
|
||||||
"license": "Apache 2.0",
|
"license": "Apache 2.0",
|
||||||
|
@ -5,6 +5,7 @@ var fs = require('fs');
|
|||||||
var async = require('async');
|
var async = require('async');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var Benchmark = require('benchmark');
|
var Benchmark = require('benchmark');
|
||||||
|
var semver = require('semver');
|
||||||
|
|
||||||
var imagemagick = require('imagemagick');
|
var imagemagick = require('imagemagick');
|
||||||
var imagemagickNative = require('imagemagick-native');
|
var imagemagickNative = require('imagemagick-native');
|
||||||
@ -314,7 +315,8 @@ async.series({
|
|||||||
},
|
},
|
||||||
png: function(callback) {
|
png: function(callback) {
|
||||||
var inputPngBuffer = fs.readFileSync(fixtures.inputPng);
|
var inputPngBuffer = fs.readFileSync(fixtures.inputPng);
|
||||||
(new Benchmark.Suite('png')).add('imagemagick-file-file', {
|
var pngSuite = new Benchmark.Suite('png');
|
||||||
|
pngSuite.add('imagemagick-file-file', {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function(deferred) {
|
fn: function(deferred) {
|
||||||
imagemagick.resize({
|
imagemagick.resize({
|
||||||
@ -422,7 +424,23 @@ async.series({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).on('cycle', function(event) {
|
});
|
||||||
|
if (semver.gte(sharp.libvipsVersion(), '7.41.0')) {
|
||||||
|
pngSuite.add('sharp-withoutAdaptiveFiltering', {
|
||||||
|
defer: true,
|
||||||
|
fn: function(deferred) {
|
||||||
|
sharp(inputPngBuffer).resize(width, height).withoutAdaptiveFiltering().toBuffer(function(err, buffer) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
} else {
|
||||||
|
assert.notStrictEqual(null, buffer);
|
||||||
|
deferred.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
pngSuite.on('cycle', function(event) {
|
||||||
console.log(' png ' + String(event.target));
|
console.log(' png ' + String(event.target));
|
||||||
}).on('complete', function() {
|
}).on('complete', function() {
|
||||||
callback(null, this.filter('fastest').pluck('name'));
|
callback(null, this.filter('fastest').pluck('name'));
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
|
||||||
|
var semver = require('semver');
|
||||||
|
|
||||||
var sharp = require('../../index');
|
var sharp = require('../../index');
|
||||||
var fixtures = require('../fixtures');
|
var fixtures = require('../fixtures');
|
||||||
|
|
||||||
@ -343,9 +345,9 @@ describe('Input/output', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('PNG compression level', function() {
|
describe('PNG output', function() {
|
||||||
|
|
||||||
it('valid', function(done) {
|
it('compression level is valid', function(done) {
|
||||||
var isValid = false;
|
var isValid = false;
|
||||||
try {
|
try {
|
||||||
sharp().compressionLevel(0);
|
sharp().compressionLevel(0);
|
||||||
@ -355,7 +357,7 @@ describe('Input/output', function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invalid', function(done) {
|
it('compression level is invalid', function(done) {
|
||||||
var isValid = false;
|
var isValid = false;
|
||||||
try {
|
try {
|
||||||
sharp().compressionLevel(-1);
|
sharp().compressionLevel(-1);
|
||||||
@ -365,6 +367,52 @@ describe('Input/output', function() {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (semver.gte(sharp.libvipsVersion(), '7.41.0')) {
|
||||||
|
it('withoutAdaptiveFiltering generates smaller file [libvips 7.41.0+]', function(done) {
|
||||||
|
// First generate with adaptive filtering
|
||||||
|
sharp(fixtures.inputPng)
|
||||||
|
.resize(320, 240)
|
||||||
|
.withoutAdaptiveFiltering(false)
|
||||||
|
.toBuffer(function(err, dataAdaptive, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(true, dataAdaptive.length > 0);
|
||||||
|
assert.strictEqual('png', info.format);
|
||||||
|
assert.strictEqual(320, info.width);
|
||||||
|
assert.strictEqual(240, info.height);
|
||||||
|
// Then generate without
|
||||||
|
sharp(fixtures.inputPng)
|
||||||
|
.resize(320, 240)
|
||||||
|
.withoutAdaptiveFiltering()
|
||||||
|
.toBuffer(function(err, dataWithoutAdaptive, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(true, dataWithoutAdaptive.length > 0);
|
||||||
|
assert.strictEqual('png', info.format);
|
||||||
|
assert.strictEqual(320, info.width);
|
||||||
|
assert.strictEqual(240, info.height);
|
||||||
|
assert.strictEqual(true, dataWithoutAdaptive.length < dataAdaptive.length);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (semver.gte(sharp.libvipsVersion(), '7.40.0')) {
|
||||||
|
it('Load TIFF from Buffer [libvips 7.40.0+]', function(done) {
|
||||||
|
var inputTiffBuffer = fs.readFileSync(fixtures.inputTiff);
|
||||||
|
sharp(inputTiffBuffer)
|
||||||
|
.resize(320, 240)
|
||||||
|
.jpeg()
|
||||||
|
.toBuffer(function(err, data, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(true, data.length > 0);
|
||||||
|
assert.strictEqual('jpeg', info.format);
|
||||||
|
assert.strictEqual(320, info.width);
|
||||||
|
assert.strictEqual(240, info.height);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user