Compare commits

...

8 Commits

Author SHA1 Message Date
Lovell Fuller
4aff57b071 Release v0.21.3 2019-01-19 14:25:37 +00:00
Maxime BACONNAIS
1df8d82fe0 Docs: overlay parameter of overlayWith is optional (#1547) 2019-01-19 14:19:41 +00:00
Lovell Fuller
98e90784f4 Docs: overlay parameter of overlayWith is optional 2019-01-19 14:11:54 +00:00
Lovell Fuller
87ea54cc66 Bump devDependencies 2019-01-19 14:06:16 +00:00
Lovell Fuller
d5e98bc8ad Split file-based input errors into missing vs invalid #1542 2019-01-19 11:59:36 +00:00
Lovell Fuller
fa69ff773a Input image decoding fail fast by default 2019-01-18 19:25:55 +00:00
Lovell Fuller
a183bb1cac Add valgrind memory leak suppressions 2019-01-18 12:08:28 +00:00
Lovell Fuller
cf62372cab Install: log the fallback to build from source
https://github.com/lovell/sharp-libvips/issues/18
2019-01-14 19:33:01 +00:00
15 changed files with 170 additions and 33 deletions

View File

@@ -41,8 +41,8 @@ Any change that modifies the existing public API should be added to the relevant
| Release | WIP branch |
| ------: | :--------- |
| v0.21.0 | teeth |
| v0.22.0 | uptake |
| v0.23.0 | vision |
Please squash your changes into a single commit using a command like `git rebase -i upstream/<wip-branch>`.

View File

@@ -11,7 +11,7 @@ If the overlay image contains an alpha channel then composition with premultipli
### Parameters
- `overlay` **([Buffer][1] \| [String][2])** Buffer containing image data or String containing the path to an image file.
- `overlay` **([Buffer][1] \| [String][2])?** Buffer containing image data or String containing the path to an image file.
- `options` **[Object][3]?**
- `options.gravity` **[String][2]** gravity at which to place the overlay. (optional, default `'centre'`)
- `options.top` **[Number][4]?** the pixel offset from the top edge.

View File

@@ -9,9 +9,8 @@
a String containing the path to an JPEG, PNG, WebP, GIF, SVG or TIFF image file.
JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
- `options` **[Object][3]?** if present, is an Object with optional attributes.
- `options.failOnError` **[Boolean][4]** by default apply a "best effort"
to decode images, even if the data is corrupt or invalid. Set this flag to true
if you'd rather halt processing and raise an error when loading invalid images. (optional, default `false`)
- `options.failOnError` **[Boolean][4]** by default halt processing and raise an error when loading invalid images.
Set this flag to `false` if you'd rather apply a "best effort" to decode images, even if the data is corrupt or invalid. (optional, default `true`)
- `options.density` **[Number][5]** number representing the DPI for vector images. (optional, default `72`)
- `options.page` **[Number][5]** page number to extract for multi-page input (GIF, TIFF) (optional, default `0`)
- `options.raw` **[Object][3]?** describes raw pixel input image data. See `raw()` for pixel ordering.

View File

@@ -4,6 +4,13 @@
Requires libvips v8.7.0.
#### v0.21.3 - 19<sup>th</sup> January 2019
* Input image decoding now fails fast, set `failOnError` to change this behaviour.
* Failed filesystem-based input now separates missing file and invalid format errors.
[#1542](https://github.com/lovell/sharp/issues/1542)
#### v0.21.2 - 13<sup>th</sup> January 2019
* Ensure all metadata is removed from PNG output unless `withMetadata` used.

View File

@@ -20,7 +20,8 @@ const distBaseUrl = process.env.npm_config_sharp_dist_base_url || process.env.SH
const fail = function (err) {
npmLog.error('sharp', err.message);
npmLog.error('sharp', 'Please see http://sharp.pixelplumbing.com/page/install');
npmLog.info('sharp', 'Attempting to build from source via node-gyp but this may fail due to the above error');
npmLog.info('sharp', 'Please see https://sharp.pixelplumbing.com/page/install for required dependencies');
process.exit(1);
};

View File

@@ -26,7 +26,7 @@ const is = require('./is');
* // sharpened, with metadata, 90% quality WebP image data. Phew!
* });
*
* @param {(Buffer|String)} overlay - Buffer containing image data or String containing the path to an image file.
* @param {(Buffer|String)} [overlay] - Buffer containing image data or String containing the path to an image file.
* @param {Object} [options]
* @param {String} [options.gravity='centre'] - gravity at which to place the overlay.
* @param {Number} [options.top] - the pixel offset from the top edge.

View File

@@ -61,9 +61,8 @@ const debuglog = util.debuglog('sharp');
* a String containing the path to an JPEG, PNG, WebP, GIF, SVG or TIFF image file.
* JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present.
* @param {Object} [options] - if present, is an Object with optional attributes.
* @param {Boolean} [options.failOnError=false] - by default apply a "best effort"
* to decode images, even if the data is corrupt or invalid. Set this flag to true
* if you'd rather halt processing and raise an error when loading invalid images.
* @param {Boolean} [options.failOnError=true] - by default halt processing and raise an error when loading invalid images.
* Set this flag to `false` if you'd rather apply a "best effort" to decode images, even if the data is corrupt or invalid.
* @param {Number} [options.density=72] - number representing the DPI for vector images.
* @param {Number} [options.page=0] - page number to extract for multi-page input (GIF, TIFF)
* @param {Object} [options.raw] - describes raw pixel input image data. See `raw()` for pixel ordering.

View File

@@ -9,7 +9,7 @@ const sharp = require('../build/Release/sharp.node');
* @private
*/
function _createInputDescriptor (input, inputOptions, containerOptions) {
const inputDescriptor = { failOnError: false };
const inputDescriptor = { failOnError: true };
if (is.string(input)) {
// filesystem
inputDescriptor.file = input;

View File

@@ -32,7 +32,7 @@ const sharp = require('../build/Release/sharp.node');
*/
function toFile (fileOut, callback) {
if (!fileOut || fileOut.length === 0) {
const errOutputInvalid = new Error('Invalid output');
const errOutputInvalid = new Error('Missing output file path');
if (is.fn(callback)) {
callback(errOutputInvalid);
} else {

View File

@@ -1,7 +1,7 @@
{
"name": "sharp",
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images",
"version": "0.21.2",
"version": "0.21.3",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp",
"contributors": [
@@ -108,7 +108,7 @@
"devDependencies": {
"async": "^2.6.1",
"cc": "^1.0.2",
"decompress-zip": "^0.3.1",
"decompress-zip": "^0.3.2",
"documentation": "^9.1.1",
"exif-reader": "^1.0.2",
"icc": "^1.0.0",

View File

@@ -137,6 +137,7 @@ namespace sharp {
case ImageType::VIPS: id = "v"; break;
case ImageType::RAW: id = "raw"; break;
case ImageType::UNKNOWN: id = "unknown"; break;
case ImageType::MISSING: id = "missing"; break;
}
return id;
}
@@ -203,6 +204,10 @@ namespace sharp {
} else if (EndsWith(loader, "Magick") || EndsWith(loader, "MagickFile")) {
imageType = ImageType::MAGICK;
}
} else {
if (EndsWith(vips::VError().what(), " not found\n")) {
imageType = ImageType::MISSING;
}
}
return imageType;
}
@@ -269,6 +274,9 @@ namespace sharp {
} else {
// From filesystem
imageType = DetermineImageType(descriptor->file.data());
if (imageType == ImageType::MISSING) {
throw vips::VError("Input file is missing");
}
if (imageType != ImageType::UNKNOWN) {
try {
vips::VOption *option = VImage::option()
@@ -291,7 +299,7 @@ namespace sharp {
throw vips::VError(std::string("Input file has corrupt header: ") + err.what());
}
} else {
throw vips::VError("Input file is missing or of an unsupported image format");
throw vips::VError("Input file contains unsupported image format");
}
}
}

View File

@@ -61,7 +61,7 @@ namespace sharp {
InputDescriptor():
buffer(nullptr),
failOnError(FALSE),
failOnError(TRUE),
bufferLength(0),
density(72.0),
rawChannels(0),
@@ -106,7 +106,8 @@ namespace sharp {
FITS,
VIPS,
RAW,
UNKNOWN
UNKNOWN,
MISSING
};
// How many tasks are in the queue?

View File

@@ -147,6 +147,47 @@
...
fun:WebPDecode
}
{
cond_libwebp_generic
Memcheck:Cond
obj:/usr/lib/x86_64-linux-gnu/libwebp.so.6.0.2
}
# tiff
{
param_tiff_write_encoded_tile
Memcheck:Param
write(buf)
fun:write
...
fun:TIFFWriteEncodedTile
}
# gsf
{
param_gsf_output_write
Memcheck:Param
write(buf)
fun:write
...
fun:gsf_output_write
}
{
value_gsf_output_write_crc32_little
Memcheck:Value8
fun:crc32_little
...
fun:gsf_output_write
}
# fontconfig
{
leak_fontconfig_FcConfigSubstituteWithPat
Memcheck:Leak
match-leak-kinds: definite,indirect
...
fun:FcConfigSubstituteWithPat
}
# libvips
{
@@ -197,6 +238,11 @@
...
fun:vips_region_prepare_to
}
{
cond_libvips_vips_stats_scan
Memcheck:Cond
fun:vips_stats_scan
}
{
value_libvips_vips_region_fill
Memcheck:Value8
@@ -204,6 +250,17 @@
fun:vips_region_fill
fun:vips_region_prepare
}
{
value_libvips_vips_hist_find_uchar_scan
Memcheck:Value8
fun:vips_hist_find_uchar_scan
}
{
value_libvips_write_webp_image
Memcheck:Value8
...
fun:write_webp_image
}
{
leak_libvips_init
Memcheck:Leak
@@ -377,6 +434,56 @@
...
fun:_ZN4node12NodePlatformC1EiPN2v817TracingControllerE
}
{
param_nodejs_delayed_task_scheduler
Memcheck:Param
epoll_ctl(event)
fun:epoll_ctl
fun:uv__io_poll
fun:uv_run
fun:_ZZN4node20BackgroundTaskRunner20DelayedTaskScheduler5StartEvENUlPvE_4_FUNES2_
}
{
param_nodejs_isolate_data
Memcheck:Param
epoll_ctl(event)
fun:epoll_ctl
fun:uv__io_poll
fun:uv_run
fun:_ZN4node5StartEPN2v87IsolateEPNS_11IsolateDataERKSt6vectorISsSaISsEES9_
}
{
param_nodejs_try_init_and_run_loop
Memcheck:Param
epoll_ctl(event)
fun:epoll_ctl
fun:uv__io_poll
fun:uv_run
fun:_ZN4node17SyncProcessRunner23TryInitializeAndRunLoopEN2v85LocalINS1_5ValueEEE
}
{
param_nodejs_run_exit_handlers
Memcheck:Param
epoll_ctl(event)
fun:epoll_ctl
fun:uv__io_poll
fun:uv_run
fun:_ZN4node7tracing5AgentD1Ev
fun:_ZN4node5._215D1Ev
fun:__run_exit_handlers
}
{
leak_nodejs_crypto_entropy_source
Memcheck:Leak
...
fun:_ZN4node6crypto13EntropySourceEPhm
}
{
leak_nodejs_debug_options
Memcheck:Leak
...
fun:_ZN4node9inspector5Agent5StartERKSsSt10shared_ptrINS_12DebugOptionsEEb
}
{
leak_nan_FunctionCallbackInfo
Memcheck:Leak

View File

@@ -6,10 +6,9 @@ const sharp = require('../../');
const fixtures = require('../fixtures');
describe('failOnError', function () {
it('handles truncated JPEG by default', function (done) {
sharp(fixtures.inputJpgTruncated)
it('handles truncated JPEG', function (done) {
sharp(fixtures.inputJpgTruncated, { failOnError: false })
.resize(320, 240)
// .toFile(fixtures.expected('truncated.jpg'), done);
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
@@ -19,10 +18,9 @@ describe('failOnError', function () {
});
});
it('handles truncated PNG by default', function (done) {
sharp(fixtures.inputPngTruncated)
it('handles truncated PNG', function (done) {
sharp(fixtures.inputPngTruncated, { failOnError: false })
.resize(320, 240)
// .toFile(fixtures.expected('truncated.png'), done);
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('png', info.format);
@@ -46,8 +44,8 @@ describe('failOnError', function () {
});
});
it('returns errors to callback for truncated JPEG when failOnError is set', function (done) {
sharp(fixtures.inputJpgTruncated, { failOnError: true }).toBuffer(function (err, data, info) {
it('returns errors to callback for truncated JPEG', function (done) {
sharp(fixtures.inputJpgTruncated).toBuffer(function (err, data, info) {
assert.ok(err.message.includes('VipsJpeg: Premature end of JPEG file'), err);
assert.strictEqual(data, null);
assert.strictEqual(info, null);
@@ -55,8 +53,8 @@ describe('failOnError', function () {
});
});
it('returns errors to callback for truncated PNG when failOnError is set', function (done) {
sharp(fixtures.inputPngTruncated, { failOnError: true }).toBuffer(function (err, data, info) {
it('returns errors to callback for truncated PNG', function (done) {
sharp(fixtures.inputPngTruncated).toBuffer(function (err, data, info) {
assert.ok(err.message.includes('vipspng: libpng read error'), err);
assert.strictEqual(data, null);
assert.strictEqual(info, null);
@@ -64,8 +62,8 @@ describe('failOnError', function () {
});
});
it('rejects promises for truncated JPEG when failOnError is set', function (done) {
sharp(fixtures.inputJpgTruncated, { failOnError: true })
it('rejects promises for truncated JPEG', function (done) {
sharp(fixtures.inputJpgTruncated)
.toBuffer()
.then(() => {
throw new Error('Expected rejection');

View File

@@ -263,7 +263,8 @@ describe('Input/output', function () {
it('Fail when output File is input File', function (done) {
sharp(fixtures.inputJpg).toFile(fixtures.inputJpg, function (err) {
assert(!!err);
assert(err instanceof Error);
assert.strictEqual('Cannot use same file for input and output', err.message);
done();
});
});
@@ -273,14 +274,16 @@ describe('Input/output', function () {
assert(false);
done();
}).catch(function (err) {
assert(!!err);
assert(err instanceof Error);
assert.strictEqual('Cannot use same file for input and output', err.message);
done();
});
});
it('Fail when output File is empty', function (done) {
sharp(fixtures.inputJpg).toFile('', function (err) {
assert(!!err);
assert(err instanceof Error);
assert.strictEqual('Missing output file path', err.message);
done();
});
});
@@ -290,7 +293,8 @@ describe('Input/output', function () {
assert(false);
done();
}).catch(function (err) {
assert(!!err);
assert(err instanceof Error);
assert.strictEqual('Missing output file path', err.message);
done();
});
});
@@ -301,6 +305,7 @@ describe('Input/output', function () {
done();
}).catch(function (err) {
assert(err instanceof Error);
assert.strictEqual('Input buffer contains unsupported image format', err.message);
done();
});
});
@@ -311,6 +316,18 @@ describe('Input/output', function () {
done();
}).catch(function (err) {
assert(err instanceof Error);
assert.strictEqual('Input buffer contains unsupported image format', err.message);
done();
});
});
it('Fail when input file path is missing', function (done) {
sharp('does-not-exist').toBuffer().then(function () {
assert(false);
done();
}).catch(function (err) {
assert(err instanceof Error);
assert.strictEqual('Input file is missing', err.message);
done();
});
});