Selected output format > unknown file extension #344

This commit is contained in:
Lovell Fuller 2016-02-07 20:13:13 +00:00
parent 5c1067c63f
commit 677b2b9089
8 changed files with 211 additions and 157 deletions

View File

@ -396,7 +396,9 @@ sharp('input.png')
#### toFile(path, [callback]) #### toFile(path, [callback])
`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. `path` is a String containing the path to write the image data to.
If an explicit output format is not selected, it will be inferred from the extension, with JPEG, PNG, WebP, TIFF and DZI supported.
`callback`, if present, is called with two arguments `(err, info)` where: `callback`, if present, is called with two arguments `(err, info)` where:

View File

@ -25,6 +25,10 @@
[#340](https://github.com/lovell/sharp/issues/340) [#340](https://github.com/lovell/sharp/issues/340)
[@janaz](https://github.com/janaz) [@janaz](https://github.com/janaz)
* Ensure selected format takes precedence over any unknown output filename extension.
[#344](https://github.com/lovell/sharp/issues/344)
[@ubaltaci](https://github.com/ubaltaci)
* Add support for libvips' PBM, PGM, PPM and FITS image format loaders. * Add support for libvips' PBM, PGM, PPM and FITS image format loaders.
[#347](https://github.com/lovell/sharp/issues/347) [#347](https://github.com/lovell/sharp/issues/347)
[@oaleynik](https://github.com/oaleynik) [@oaleynik](https://github.com/oaleynik)

View File

@ -86,7 +86,8 @@ var Sharp = function(input, options) {
// overlay // overlay
overlayPath: '', overlayPath: '',
// output options // output options
output: '__input', formatOut: 'input',
fileOut: '',
progressive: false, progressive: false,
quality: 80, quality: 80,
compressionLevel: 6, compressionLevel: 6,
@ -667,8 +668,8 @@ Sharp.prototype.limitInputPixels = function(limit) {
/* /*
Write output image data to a file Write output image data to a file
*/ */
Sharp.prototype.toFile = function(output, callback) { Sharp.prototype.toFile = function(fileOut, callback) {
if (!output || output.length === 0) { if (!fileOut || fileOut.length === 0) {
var errOutputInvalid = new Error('Invalid output'); var errOutputInvalid = new Error('Invalid output');
if (typeof callback === 'function') { if (typeof callback === 'function') {
callback(errOutputInvalid); callback(errOutputInvalid);
@ -676,7 +677,7 @@ Sharp.prototype.toFile = function(output, callback) {
return BluebirdPromise.reject(errOutputInvalid); return BluebirdPromise.reject(errOutputInvalid);
} }
} else { } else {
if (this.options.fileIn === output) { if (this.options.fileIn === fileOut) {
var errOutputIsInput = new Error('Cannot use same file for input and output'); var errOutputIsInput = new Error('Cannot use same file for input and output');
if (typeof callback === 'function') { if (typeof callback === 'function') {
callback(errOutputIsInput); callback(errOutputIsInput);
@ -684,7 +685,7 @@ Sharp.prototype.toFile = function(output, callback) {
return BluebirdPromise.reject(errOutputIsInput); return BluebirdPromise.reject(errOutputIsInput);
} }
} else { } else {
this.options.output = output; this.options.fileOut = fileOut;
return this._pipeline(callback); return this._pipeline(callback);
} }
} }
@ -702,7 +703,7 @@ Sharp.prototype.toBuffer = function(callback) {
Force JPEG output Force JPEG output
*/ */
Sharp.prototype.jpeg = function() { Sharp.prototype.jpeg = function() {
this.options.output = '__jpeg'; this.options.formatOut = 'jpeg';
return this; return this;
}; };
@ -710,7 +711,7 @@ Sharp.prototype.jpeg = function() {
Force PNG output Force PNG output
*/ */
Sharp.prototype.png = function() { Sharp.prototype.png = function() {
this.options.output = '__png'; this.options.formatOut = 'png';
return this; return this;
}; };
@ -718,7 +719,7 @@ Sharp.prototype.png = function() {
Force WebP output Force WebP output
*/ */
Sharp.prototype.webp = function() { Sharp.prototype.webp = function() {
this.options.output = '__webp'; this.options.formatOut = 'webp';
return this; return this;
}; };
@ -726,7 +727,7 @@ Sharp.prototype.webp = function() {
Force raw, uint8 output Force raw, uint8 output
*/ */
Sharp.prototype.raw = function() { Sharp.prototype.raw = function() {
this.options.output = '__raw'; this.options.formatOut = 'raw';
return this; return this;
}; };
@ -734,15 +735,17 @@ Sharp.prototype.raw = function() {
Force output to a given format Force output to a given format
@param format is either the id as a String or an Object with an 'id' attribute @param format is either the id as a String or an Object with an 'id' attribute
*/ */
Sharp.prototype.toFormat = function(format) { Sharp.prototype.toFormat = function(formatOut) {
var id = format; if (isObject(formatOut) && isDefined(formatOut.id)) {
if (typeof format === 'object') { formatOut = formatOut.id;
id = format.id;
} }
if (typeof id === 'string' && typeof module.exports.format[id] === 'object' && typeof this[id] === 'function') { if (
this[id](); isDefined(formatOut) &&
['jpeg', 'png', 'webp', 'raw', 'tiff', 'dz', 'input'].indexOf(formatOut) !== -1
) {
this.options.formatOut = formatOut;
} else { } else {
throw new Error('Unsupported format ' + format); throw new Error('Unsupported output format ' + formatOut);
} }
return this; return this;
}; };

View File

@ -53,6 +53,26 @@ namespace sharp {
return EndsWith(str, ".dzi") || EndsWith(str, ".DZI"); return EndsWith(str, ".dzi") || EndsWith(str, ".DZI");
} }
/*
Provide a string identifier for the given image type.
*/
std::string ImageTypeId(ImageType const imageType) {
std::string id;
switch (imageType) {
case ImageType::JPEG: id = "jpeg"; break;
case ImageType::PNG: id = "png"; break;
case ImageType::WEBP: id = "webp"; break;
case ImageType::TIFF: id = "tiff"; break;
case ImageType::MAGICK: id = "magick"; break;
case ImageType::OPENSLIDE: id = "openslide"; break;
case ImageType::PPM: id = "ppm"; break;
case ImageType::FITS: id = "fits"; break;
case ImageType::RAW: id = "raw"; break;
case ImageType::UNKNOWN: id = "unknown"; break;
}
return id;
}
/* /*
Determine image format of a buffer. Determine image format of a buffer.
*/ */

View File

@ -34,6 +34,11 @@ namespace sharp {
bool IsTiff(std::string const &str); bool IsTiff(std::string const &str);
bool IsDz(std::string const &str); bool IsDz(std::string const &str);
/*
Provide a string identifier for the given image type.
*/
std::string ImageTypeId(ImageType const imageType);
/* /*
Determine image format of a buffer. Determine image format of a buffer.
*/ */

View File

@ -33,6 +33,7 @@ using vips::VImage;
using vips::VError; using vips::VError;
using sharp::ImageType; using sharp::ImageType;
using sharp::ImageTypeId;
using sharp::DetermineImageType; using sharp::DetermineImageType;
using sharp::HasProfile; using sharp::HasProfile;
using sharp::HasAlpha; using sharp::HasAlpha;
@ -113,18 +114,7 @@ class MetadataWorker : public AsyncWorker {
} }
if (imageType != ImageType::UNKNOWN) { if (imageType != ImageType::UNKNOWN) {
// Image type // Image type
switch (imageType) { baton->format = ImageTypeId(imageType);
case ImageType::JPEG: baton->format = "jpeg"; break;
case ImageType::PNG: baton->format = "png"; break;
case ImageType::WEBP: baton->format = "webp"; break;
case ImageType::TIFF: baton->format = "tiff"; break;
case ImageType::MAGICK: baton->format = "magick"; break;
case ImageType::OPENSLIDE: baton->format = "openslide"; break;
case ImageType::PPM: baton->format = "ppm"; break;
case ImageType::FITS: baton->format = "fits"; break;
case ImageType::RAW: baton->format = "raw"; break;
case ImageType::UNKNOWN: break;
}
// VipsImage attributes // VipsImage attributes
baton->width = image.width(); baton->width = image.width();
baton->height = image.height(); baton->height = image.height();

View File

@ -49,6 +49,7 @@ using sharp::Blur;
using sharp::Sharpen; using sharp::Sharpen;
using sharp::ImageType; using sharp::ImageType;
using sharp::ImageTypeId;
using sharp::DetermineImageType; using sharp::DetermineImageType;
using sharp::HasProfile; using sharp::HasProfile;
using sharp::HasAlpha; using sharp::HasAlpha;
@ -82,8 +83,8 @@ struct PipelineBaton {
int rawWidth; int rawWidth;
int rawHeight; int rawHeight;
int rawChannels; int rawChannels;
std::string output; std::string formatOut;
std::string outputFormat; std::string fileOut;
void *bufferOut; void *bufferOut;
size_t bufferOutLength; size_t bufferOutLength;
int topOffsetPre; int topOffsetPre;
@ -139,7 +140,8 @@ struct PipelineBaton {
rawWidth(0), rawWidth(0),
rawHeight(0), rawHeight(0),
rawChannels(0), rawChannels(0),
outputFormat(""), formatOut(""),
fileOut(""),
bufferOutLength(0), bufferOutLength(0),
topOffsetPre(-1), topOffsetPre(-1),
topOffsetPost(-1), topOffsetPost(-1),
@ -707,62 +709,75 @@ class PipelineWorker : public AsyncWorker {
} }
// Output // Output
if (baton->output == "__jpeg" || (baton->output == "__input" && inputImageType == ImageType::JPEG)) { if (baton->fileOut == "") {
// Write JPEG to buffer // Buffer output
baton->bufferOut = static_cast<char*>(const_cast<void*>(vips_blob_get(image.jpegsave_buffer(VImage::option() if (baton->formatOut == "jpeg" || (baton->formatOut == "input" && inputImageType == ImageType::JPEG)) {
->set("strip", !baton->withMetadata) // Write JPEG to buffer
->set("Q", baton->quality) baton->bufferOut = static_cast<char*>(const_cast<void*>(vips_blob_get(image.jpegsave_buffer(VImage::option()
->set("optimize_coding", TRUE) ->set("strip", !baton->withMetadata)
->set("no_subsample", baton->withoutChromaSubsampling) ->set("Q", baton->quality)
->set("trellis_quant", baton->trellisQuantisation) ->set("optimize_coding", TRUE)
->set("overshoot_deringing", baton->overshootDeringing) ->set("no_subsample", baton->withoutChromaSubsampling)
->set("optimize_scans", baton->optimiseScans) ->set("trellis_quant", baton->trellisQuantisation)
->set("interlace", baton->progressive) ->set("overshoot_deringing", baton->overshootDeringing)
), &baton->bufferOutLength))); ->set("optimize_scans", baton->optimiseScans)
baton->outputFormat = "jpeg"; ->set("interlace", baton->progressive)
} else if (baton->output == "__png" || (baton->output == "__input" && inputImageType == ImageType::PNG)) { ), &baton->bufferOutLength)));
// Write PNG to buffer baton->formatOut = "jpeg";
baton->bufferOut = static_cast<char*>(const_cast<void*>(vips_blob_get(image.pngsave_buffer(VImage::option() } else if (baton->formatOut == "png" || (baton->formatOut == "input" && inputImageType == ImageType::PNG)) {
->set("strip", !baton->withMetadata) // Write PNG to buffer
->set("compression", baton->compressionLevel) baton->bufferOut = static_cast<char*>(const_cast<void*>(vips_blob_get(image.pngsave_buffer(VImage::option()
->set("interlace", baton->progressive) ->set("strip", !baton->withMetadata)
->set("filter", baton->withoutAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_NONE : VIPS_FOREIGN_PNG_FILTER_ALL) ->set("compression", baton->compressionLevel)
), &baton->bufferOutLength))); ->set("interlace", baton->progressive)
baton->outputFormat = "png"; ->set("filter", baton->withoutAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_NONE : VIPS_FOREIGN_PNG_FILTER_ALL)
} else if (baton->output == "__webp" || (baton->output == "__input" && inputImageType == ImageType::WEBP)) { ), &baton->bufferOutLength)));
// Write WEBP to buffer baton->formatOut = "png";
baton->bufferOut = static_cast<char*>(const_cast<void*>(vips_blob_get(image.webpsave_buffer(VImage::option() } else if (baton->formatOut == "webp" || (baton->formatOut == "input" && inputImageType == ImageType::WEBP)) {
->set("strip", !baton->withMetadata) // Write WEBP to buffer
->set("Q", baton->quality) baton->bufferOut = static_cast<char*>(const_cast<void*>(vips_blob_get(image.webpsave_buffer(VImage::option()
), &baton->bufferOutLength))); ->set("strip", !baton->withMetadata)
baton->outputFormat = "webp"; ->set("Q", baton->quality)
} else if (baton->output == "__raw") { ), &baton->bufferOutLength)));
// Write raw, uncompressed image data to buffer baton->formatOut = "webp";
if (baton->greyscale || image.interpretation() == VIPS_INTERPRETATION_B_W) { } else if (baton->formatOut == "raw") {
// Extract first band for greyscale image // Write raw, uncompressed image data to buffer
image = image[0]; if (baton->greyscale || image.interpretation() == VIPS_INTERPRETATION_B_W) {
} // Extract first band for greyscale image
if (image.format() != VIPS_FORMAT_UCHAR) { image = image[0];
// Cast pixels to uint8 (unsigned char) }
image = image.cast(VIPS_FORMAT_UCHAR); if (image.format() != VIPS_FORMAT_UCHAR) {
} // Cast pixels to uint8 (unsigned char)
// Get raw image data image = image.cast(VIPS_FORMAT_UCHAR);
baton->bufferOut = static_cast<char*>(image.write_to_memory(&baton->bufferOutLength)); }
if (baton->bufferOut == nullptr) { // Get raw image data
(baton->err).append("Could not allocate enough memory for raw output"); baton->bufferOut = static_cast<char*>(image.write_to_memory(&baton->bufferOutLength));
if (baton->bufferOut == nullptr) {
(baton->err).append("Could not allocate enough memory for raw output");
return Error();
}
baton->formatOut = "raw";
} else {
// Unsupported output format
(baton->err).append("Unsupported output format ");
if (baton->formatOut == "input") {
(baton->err).append(ImageTypeId(inputImageType));
} else {
(baton->err).append(baton->formatOut);
}
return Error(); return Error();
} }
baton->outputFormat = "raw";
} else { } else {
bool outputJpeg = IsJpeg(baton->output); // File output
bool outputPng = IsPng(baton->output); bool isJpeg = IsJpeg(baton->fileOut);
bool outputWebp = IsWebp(baton->output); bool isPng = IsPng(baton->fileOut);
bool outputTiff = IsTiff(baton->output); bool isWebp = IsWebp(baton->fileOut);
bool outputDz = IsDz(baton->output); bool isTiff = IsTiff(baton->fileOut);
bool matchInput = !(outputJpeg || outputPng || outputWebp || outputTiff || outputDz); bool isDz = IsDz(baton->fileOut);
if (outputJpeg || (matchInput && inputImageType == ImageType::JPEG)) { bool matchInput = baton->formatOut == "input" && !(isJpeg || isPng || isWebp || isTiff || isDz);
if (baton->formatOut == "jpeg" || isJpeg || (matchInput && inputImageType == ImageType::JPEG)) {
// Write JPEG to file // Write JPEG to file
image.jpegsave(const_cast<char*>(baton->output.data()), VImage::option() image.jpegsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
->set("strip", !baton->withMetadata) ->set("strip", !baton->withMetadata)
->set("Q", baton->quality) ->set("Q", baton->quality)
->set("optimize_coding", TRUE) ->set("optimize_coding", TRUE)
@ -772,41 +787,42 @@ class PipelineWorker : public AsyncWorker {
->set("optimize_scans", baton->optimiseScans) ->set("optimize_scans", baton->optimiseScans)
->set("interlace", baton->progressive) ->set("interlace", baton->progressive)
); );
baton->outputFormat = "jpeg"; baton->formatOut = "jpeg";
} else if (outputPng || (matchInput && inputImageType == ImageType::PNG)) { } else if (baton->formatOut == "png" || isPng || (matchInput && inputImageType == ImageType::PNG)) {
// Write PNG to file // Write PNG to file
image.pngsave(const_cast<char*>(baton->output.data()), VImage::option() image.pngsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
->set("strip", !baton->withMetadata) ->set("strip", !baton->withMetadata)
->set("compression", baton->compressionLevel) ->set("compression", baton->compressionLevel)
->set("interlace", baton->progressive) ->set("interlace", baton->progressive)
->set("filter", baton->withoutAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_NONE : VIPS_FOREIGN_PNG_FILTER_ALL) ->set("filter", baton->withoutAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_NONE : VIPS_FOREIGN_PNG_FILTER_ALL)
); );
baton->outputFormat = "png"; baton->formatOut = "png";
} else if (outputWebp || (matchInput && inputImageType == ImageType::WEBP)) { } else if (baton->formatOut == "webp" || isWebp || (matchInput && inputImageType == ImageType::WEBP)) {
// Write WEBP to file // Write WEBP to file
image.webpsave(const_cast<char*>(baton->output.data()), VImage::option() image.webpsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
->set("strip", !baton->withMetadata) ->set("strip", !baton->withMetadata)
->set("Q", baton->quality) ->set("Q", baton->quality)
); );
baton->outputFormat = "webp"; baton->formatOut = "webp";
} else if (outputTiff || (matchInput && inputImageType == ImageType::TIFF)) { } else if (baton->formatOut == "tiff" || isTiff || (matchInput && inputImageType == ImageType::TIFF)) {
// Write TIFF to file // Write TIFF to file
image.tiffsave(const_cast<char*>(baton->output.data()), VImage::option() image.tiffsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
->set("strip", !baton->withMetadata) ->set("strip", !baton->withMetadata)
->set("Q", baton->quality) ->set("Q", baton->quality)
->set("compression", VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) ->set("compression", VIPS_FOREIGN_TIFF_COMPRESSION_JPEG)
); );
baton->outputFormat = "tiff"; baton->formatOut = "tiff";
} else if (outputDz) { } else if (baton->formatOut == "dz" || IsDz(baton->fileOut)) {
// Write DZ to file // Write DZ to file
image.dzsave(const_cast<char*>(baton->output.data()), VImage::option() image.dzsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
->set("strip", !baton->withMetadata) ->set("strip", !baton->withMetadata)
->set("tile_size", baton->tileSize) ->set("tile_size", baton->tileSize)
->set("overlap", baton->tileOverlap) ->set("overlap", baton->tileOverlap)
); );
baton->outputFormat = "dz"; baton->formatOut = "dz";
} else { } else {
(baton->err).append("Unsupported output " + baton->output); // Unsupported output format
(baton->err).append("Unsupported output format " + baton->fileOut);
return Error(); return Error();
} }
} }
@ -840,7 +856,7 @@ class PipelineWorker : public AsyncWorker {
} }
// Info Object // Info Object
Local<Object> info = New<Object>(); Local<Object> info = New<Object>();
Set(info, New("format").ToLocalChecked(), New<String>(baton->outputFormat).ToLocalChecked()); Set(info, New("format").ToLocalChecked(), New<String>(baton->formatOut).ToLocalChecked());
Set(info, New("width").ToLocalChecked(), New<Uint32>(static_cast<uint32_t>(width))); Set(info, New("width").ToLocalChecked(), New<Uint32>(static_cast<uint32_t>(width)));
Set(info, New("height").ToLocalChecked(), New<Uint32>(static_cast<uint32_t>(height))); Set(info, New("height").ToLocalChecked(), New<Uint32>(static_cast<uint32_t>(height)));
Set(info, New("channels").ToLocalChecked(), New<Uint32>(static_cast<uint32_t>(baton->channels))); Set(info, New("channels").ToLocalChecked(), New<Uint32>(static_cast<uint32_t>(baton->channels)));
@ -856,7 +872,7 @@ class PipelineWorker : public AsyncWorker {
} else { } else {
// Add file size to info // Add file size to info
GStatBuf st; GStatBuf st;
g_stat(baton->output.data(), &st); g_stat(baton->fileOut.data(), &st);
Set(info, New("size").ToLocalChecked(), New<Uint32>(static_cast<uint32_t>(st.st_size))); Set(info, New("size").ToLocalChecked(), New<Uint32>(static_cast<uint32_t>(st.st_size)));
argv[1] = info; argv[1] = info;
} }
@ -1091,8 +1107,9 @@ NAN_METHOD(pipeline) {
baton->optimiseScans = attrAs<bool>(options, "optimiseScans"); baton->optimiseScans = attrAs<bool>(options, "optimiseScans");
baton->withMetadata = attrAs<bool>(options, "withMetadata"); baton->withMetadata = attrAs<bool>(options, "withMetadata");
baton->withMetadataOrientation = attrAs<int32_t>(options, "withMetadataOrientation"); baton->withMetadataOrientation = attrAs<int32_t>(options, "withMetadataOrientation");
// Output filename or __format for Buffer // Output
baton->output = attrAsStr(options, "output"); baton->formatOut = attrAsStr(options, "formatOut");
baton->fileOut = attrAsStr(options, "fileOut");
baton->tileSize = attrAs<int32_t>(options, "tileSize"); baton->tileSize = attrAs<int32_t>(options, "tileSize");
baton->tileOverlap = attrAs<int32_t>(options, "tileOverlap"); baton->tileOverlap = attrAs<int32_t>(options, "tileOverlap");
// Function to notify of queue length changes // Function to notify of queue length changes

View File

@ -392,76 +392,89 @@ describe('Input/output', function() {
}); });
}); });
describe('Output filename without extension uses input format', function() { describe('Output filename with unknown extension', function() {
it('JPEG', function(done) { it('Match JPEG input', function(done) {
sharp(fixtures.inputJpg).resize(320, 80).toFile(fixtures.outputZoinks, function(err, info) { sharp(fixtures.inputJpg)
if (err) throw err; .resize(320, 80)
assert.strictEqual(true, info.size > 0); .toFile(fixtures.outputZoinks, function(err, info) {
assert.strictEqual('jpeg', info.format);
assert.strictEqual(320, info.width);
assert.strictEqual(80, info.height);
fs.unlinkSync(fixtures.outputZoinks);
done();
});
});
it('PNG', function(done) {
sharp(fixtures.inputPng).resize(320, 80).toFile(fixtures.outputZoinks, function(err, info) {
if (err) throw err;
assert.strictEqual(true, info.size > 0);
assert.strictEqual('png', info.format);
assert.strictEqual(320, info.width);
assert.strictEqual(80, info.height);
fs.unlinkSync(fixtures.outputZoinks);
done();
});
});
it('Transparent PNG', function(done) {
sharp(fixtures.inputPngWithTransparency).resize(320, 80).toFile(fixtures.outputZoinks, function(err, info) {
if (err) throw err;
assert.strictEqual(true, info.size > 0);
assert.strictEqual('png', info.format);
assert.strictEqual(320, info.width);
assert.strictEqual(80, info.height);
done();
});
});
if (sharp.format.webp.input.file) {
it('WebP', function(done) {
sharp(fixtures.inputWebP).resize(320, 80).toFile(fixtures.outputZoinks, function(err, info) {
if (err) throw err; if (err) throw err;
assert.strictEqual(true, info.size > 0); assert.strictEqual(true, info.size > 0);
assert.strictEqual('webp', info.format); assert.strictEqual('jpeg', info.format);
assert.strictEqual(320, info.width); assert.strictEqual(320, info.width);
assert.strictEqual(80, info.height); assert.strictEqual(80, info.height);
fs.unlinkSync(fixtures.outputZoinks); fs.unlinkSync(fixtures.outputZoinks);
done(); done();
}); });
});
it('Match PNG input', function(done) {
sharp(fixtures.inputPng)
.resize(320, 80)
.toFile(fixtures.outputZoinks, function(err, info) {
if (err) throw err;
assert.strictEqual(true, info.size > 0);
assert.strictEqual('png', info.format);
assert.strictEqual(320, info.width);
assert.strictEqual(80, info.height);
fs.unlinkSync(fixtures.outputZoinks);
done();
});
});
if (sharp.format.webp.input.file) {
it('Match WebP input', function(done) {
sharp(fixtures.inputWebP)
.resize(320, 80)
.toFile(fixtures.outputZoinks, function(err, info) {
if (err) throw err;
assert.strictEqual(true, info.size > 0);
assert.strictEqual('webp', info.format);
assert.strictEqual(320, info.width);
assert.strictEqual(80, info.height);
fs.unlinkSync(fixtures.outputZoinks);
done();
});
}); });
} }
it('TIFF', function(done) { it('Match TIFF input', function(done) {
sharp(fixtures.inputTiff).resize(320, 80).toFile(fixtures.outputZoinks, function(err, info) { sharp(fixtures.inputTiff)
if (err) throw err; .resize(320, 80)
assert.strictEqual(true, info.size > 0); .toFile(fixtures.outputZoinks, function(err, info) {
assert.strictEqual('tiff', info.format); if (err) throw err;
assert.strictEqual(320, info.width); assert.strictEqual(true, info.size > 0);
assert.strictEqual(80, info.height); assert.strictEqual('tiff', info.format);
fs.unlinkSync(fixtures.outputZoinks); assert.strictEqual(320, info.width);
done(); assert.strictEqual(80, info.height);
}); fs.unlinkSync(fixtures.outputZoinks);
done();
});
}); });
it('Fail with GIF', function(done) { it('Match GIF input, therefore fail', function(done) {
sharp(fixtures.inputGif).resize(320, 80).toFile(fixtures.outputZoinks, function(err) { sharp(fixtures.inputGif)
assert(!!err); .resize(320, 80)
done(); .toFile(fixtures.outputZoinks, function(err) {
}); assert(!!err);
done();
});
}); });
it('Force JPEG format for PNG input', function(done) {
sharp(fixtures.inputPng)
.resize(320, 80)
.jpeg()
.toFile(fixtures.outputZoinks, function(err, info) {
if (err) throw err;
assert.strictEqual(true, info.size > 0);
assert.strictEqual('jpeg', info.format);
assert.strictEqual(320, info.width);
assert.strictEqual(80, info.height);
fs.unlinkSync(fixtures.outputZoinks);
done();
});
});
}); });
describe('PNG output', function() { describe('PNG output', function() {