Compare commits

...

2 Commits

Author SHA1 Message Date
Lovell Fuller
6d18c6fdc6 Add Media Type to metadata response #4492 2026-02-01 21:20:16 +00:00
Lovell Fuller
2291c0b864 Switch from custom VError to standard runtime_error 2026-01-23 22:42:23 +00:00
13 changed files with 123 additions and 39 deletions

View File

@@ -18,6 +18,7 @@ Dimensions in the response will respect the `page` and `pages` properties of the
A `Promise` is returned when `callback` is not provided.
- `format`: Name of decoder used to parse image e.g. `jpeg`, `png`, `webp`, `gif`, `svg`, `heif`, `tiff`
- `mediaType`: Media Type (MIME Type) e.g. `image/jpeg`, `image/png`, `image/svg+xml`, `image/avif`
- `size`: Total size of image in bytes, for Stream and Buffer input only
- `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
- `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)

View File

@@ -43,4 +43,7 @@ slug: changelog/v0.35.0
* Ensure HEIF primary item is used as default page/frame.
[#4487](https://github.com/lovell/sharp/issues/4487)
* Add image Media Type (MIME Type) to metadata response.
[#4492](https://github.com/lovell/sharp/issues/4492)
* Add WebP `exact` option for control over transparent pixel colour values.

View File

@@ -567,6 +567,7 @@ function _isStreamInput () {
* A `Promise` is returned when `callback` is not provided.
*
* - `format`: Name of decoder used to parse image e.g. `jpeg`, `png`, `webp`, `gif`, `svg`, `heif`, `tiff`
* - `mediaType`: Media Type (MIME Type) e.g. `image/jpeg`, `image/png`, `image/svg+xml`, `image/avif`
* - `size`: Total size of image in bytes, for Stream and Buffer input only
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)

View File

@@ -510,11 +510,11 @@ namespace sharp {
option = GetOptionsForImageType(imageType, descriptor);
image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
}
} catch (vips::VError const &err) {
throw vips::VError(std::string("Input buffer has corrupt header: ") + err.what());
} catch (std::runtime_error const &err) {
throw std::runtime_error(std::string("Input buffer has corrupt header: ") + err.what());
}
} else {
throw vips::VError("Input buffer contains unsupported image format");
throw std::runtime_error("Input buffer contains unsupported image format");
}
}
} else {
@@ -585,10 +585,10 @@ namespace sharp {
imageType = DetermineImageType(descriptor->file.data());
if (imageType == ImageType::MISSING) {
if (descriptor->file.find("<svg") != std::string::npos) {
throw vips::VError("Input file is missing, did you mean "
throw std::runtime_error("Input file is missing, did you mean "
"sharp(Buffer.from('" + descriptor->file.substr(0, 8) + "...')?");
}
throw vips::VError("Input file is missing: " + descriptor->file);
throw std::runtime_error("Input file is missing: " + descriptor->file);
}
if (imageType != ImageType::UNKNOWN) {
try {
@@ -600,11 +600,11 @@ namespace sharp {
option = GetOptionsForImageType(imageType, descriptor);
image = VImage::new_from_file(descriptor->file.data(), option);
}
} catch (vips::VError const &err) {
throw vips::VError(std::string("Input file has corrupt header: ") + err.what());
} catch (std::runtime_error const &err) {
throw std::runtime_error(std::string("Input file has corrupt header: ") + err.what());
}
} else {
throw vips::VError("Input file contains unsupported image format");
throw std::runtime_error("Input file contains unsupported image format");
}
}
}
@@ -612,7 +612,7 @@ namespace sharp {
// Limit input images to a given number of pixels, where pixels = width * height
if (descriptor->limitInputPixels > 0 &&
static_cast<uint64_t>(image.width()) * image.height() > descriptor->limitInputPixels) {
throw vips::VError("Input image exceeds pixel limit");
throw std::runtime_error("Input image exceeds pixel limit");
}
return std::make_tuple(image, imageType);
}
@@ -788,19 +788,19 @@ namespace sharp {
: image.height();
if (imageType == ImageType::JPEG) {
if (image.width() > 65535 || height > 65535) {
throw vips::VError("Processed image is too large for the JPEG format");
throw std::runtime_error("Processed image is too large for the JPEG format");
}
} else if (imageType == ImageType::WEBP) {
if (image.width() > 16383 || height > 16383) {
throw vips::VError("Processed image is too large for the WebP format");
throw std::runtime_error("Processed image is too large for the WebP format");
}
} else if (imageType == ImageType::GIF) {
if (image.width() > 65535 || height > 65535) {
throw vips::VError("Processed image is too large for the GIF format");
throw std::runtime_error("Processed image is too large for the GIF format");
}
} else if (imageType == ImageType::HEIF) {
if (image.width() > 16384 || height > 16384) {
throw vips::VError("Processed image is too large for the HEIF format");
throw std::runtime_error("Processed image is too large for the HEIF format");
}
}
}

View File

@@ -31,7 +31,7 @@ class MetadataWorker : public Napi::AsyncWorker {
sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
try {
std::tie(image, imageType) = OpenInput(baton->input);
} catch (vips::VError const &err) {
} catch (std::runtime_error const &err) {
(baton->err).append(err.what());
}
if (imageType != sharp::ImageType::UNKNOWN) {
@@ -151,6 +151,50 @@ class MetadataWorker : public Napi::AsyncWorker {
}
// PNG comments
vips_image_map(image.get_image(), readPNGComment, &baton->comments);
// Media type
std::string mediaType;
switch (imageType) {
case sharp::ImageType::JPEG:
case sharp::ImageType::PNG:
case sharp::ImageType::WEBP:
case sharp::ImageType::JP2:
case sharp::ImageType::TIFF:
case sharp::ImageType::GIF:
case sharp::ImageType::FITS:
case sharp::ImageType::JXL:
baton->mediaType = "image/" + baton->format;
break;
case sharp::ImageType::SVG:
baton->mediaType = "image/svg+xml";
break;
case sharp::ImageType::HEIF:
if (baton->compression == "av1") {
baton->mediaType = "image/avif";
} else if (baton->compression == "hevc") {
baton->mediaType = "image/heic";
}
break;
case sharp::ImageType::PDF:
baton->mediaType = "application/pdf";
break;
case sharp::ImageType::OPENSLIDE:
baton->mediaType = "image/tiff";
break;
case sharp::ImageType::PPM:
baton->mediaType = "image/x-portable-pixmap";
break;
case sharp::ImageType::EXR:
baton->mediaType = "image/x-exr";
break;
case sharp::ImageType::RAD:
baton->mediaType = "image/vnd.radiance";
break;
case sharp::ImageType::UHDR:
baton->mediaType = "image/jpeg";
break;
default:
break;
}
}
// Clean up
@@ -172,6 +216,9 @@ class MetadataWorker : public Napi::AsyncWorker {
if (baton->err.empty()) {
Napi::Object info = Napi::Object::New(env);
info.Set("format", baton->format);
if (!baton->mediaType.empty()) {
info.Set("mediaType", baton->mediaType);
}
if (baton->input->bufferLength > 0) {
info.Set("size", baton->input->bufferLength);
}

View File

@@ -19,6 +19,7 @@ struct MetadataBaton {
sharp::InputDescriptor *input;
// Output
std::string format;
std::string mediaType;
int width;
int height;
std::string space;

View File

@@ -14,7 +14,6 @@
#include "./operations.h"
using vips::VImage;
using vips::VError;
namespace sharp {
/*
@@ -287,7 +286,7 @@ namespace sharp {
*/
VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt, int const margin) {
if (image.width() < 3 && image.height() < 3) {
throw VError("Image to trim must be at least 3x3 pixels");
throw std::runtime_error("Image to trim must be at least 3x3 pixels");
}
if (background.size() == 0) {
// Top-left pixel provides the default background colour if none is given
@@ -361,7 +360,7 @@ namespace sharp {
VImage Linear(VImage image, std::vector<double> const a, std::vector<double> const b) {
size_t const bands = static_cast<size_t>(image.bands());
if (a.size() > bands) {
throw VError("Band expansion using linear is unsupported");
throw std::runtime_error("Band expansion using linear is unsupported");
}
bool const uchar = !Is16Bit(image.interpretation());
if (image.has_alpha() && a.size() != bands && (a.size() == 1 || a.size() == bands - 1 || bands - 1 == 1)) {

View File

@@ -274,7 +274,7 @@ class PipelineWorker : public Napi::AsyncWorker {
}
sharp::SetDensity(image, baton->input->density);
if (image.width() > 32767 || image.height() > 32767) {
throw vips::VError("Input SVG image will exceed 32767x32767 pixel limit when scaled");
throw std::runtime_error("Input SVG image will exceed 32767x32767 pixel limit when scaled");
}
} else if (inputImageType == sharp::ImageType::PDF) {
if (baton->input->buffer != nullptr) {
@@ -290,7 +290,7 @@ class PipelineWorker : public Napi::AsyncWorker {
}
} else {
if (inputImageType == sharp::ImageType::SVG && (image.width() > 32767 || image.height() > 32767)) {
throw vips::VError("Input SVG image exceeds 32767x32767 pixel limit");
throw std::runtime_error("Input SVG image exceeds 32767x32767 pixel limit");
}
}
if (baton->input->autoOrient) {
@@ -675,7 +675,7 @@ class PipelineWorker : public Napi::AsyncWorker {
// Verify within current dimensions
if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
throw vips::VError("Image to composite must have same dimensions or smaller");
throw std::runtime_error("Image to composite must have same dimensions or smaller");
}
// Check if overlay is tiled
if (composite->tile) {
@@ -1086,20 +1086,19 @@ class PipelineWorker : public Napi::AsyncWorker {
// Get raw image data
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();
throw std::runtime_error("Could not allocate enough memory for raw output");
}
baton->formatOut = "raw";
} else {
// Unsupported output format
(baton->err).append("Unsupported output format ");
auto unsupported = std::string("Unsupported output format ");
if (baton->formatOut == "input") {
(baton->err).append("when trying to match input format of ");
(baton->err).append(ImageTypeId(inputImageType));
unsupported.append("when trying to match input format of ");
unsupported.append(ImageTypeId(inputImageType));
} else {
(baton->err).append(baton->formatOut);
unsupported.append(baton->formatOut);
}
return Error();
throw std::runtime_error(unsupported);
}
} else {
// File output
@@ -1274,7 +1273,7 @@ class PipelineWorker : public Napi::AsyncWorker {
return Error();
}
}
} catch (vips::VError const &err) {
} catch (std::runtime_error const &err) {
char const *what = err.what();
if (what && what[0]) {
(baton->err).append(what);
@@ -1306,7 +1305,6 @@ class PipelineWorker : public Napi::AsyncWorker {
}
warning = sharp::VipsWarningPop();
}
if (baton->err.empty()) {
int width = baton->width;
int height = baton->height;
@@ -1407,7 +1405,7 @@ class PipelineWorker : public Napi::AsyncWorker {
void MultiPageUnsupported(int const pages, std::string op) {
if (pages > 1) {
throw vips::VError(op + " is not supported for multi-page images");
throw std::runtime_error(op + " is not supported for multi-page images");
}
}

View File

@@ -39,7 +39,7 @@ class StatsWorker : public Napi::AsyncWorker {
sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
try {
std::tie(image, imageType) = OpenInput(baton->input);
} catch (vips::VError const &err) {
} catch (std::runtime_error const &err) {
(baton->err).append(err.what());
}
if (imageType != sharp::ImageType::UNKNOWN) {
@@ -92,7 +92,7 @@ class StatsWorker : public Napi::AsyncWorker {
baton->dominantRed = dx * 16 + 8;
baton->dominantGreen = dy * 16 + 8;
baton->dominantBlue = dz * 16 + 8;
} catch (vips::VError const &err) {
} catch (std::runtime_error const &err) {
(baton->err).append(err.what());
}
}
@@ -112,7 +112,6 @@ class StatsWorker : public Napi::AsyncWorker {
debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
warning = sharp::VipsWarningPop();
}
if (baton->err.empty()) {
// Stats Object
Napi::Object info = Napi::Object::New(env);

View File

@@ -244,7 +244,7 @@ Napi::Value _maxColourDistance(const Napi::CallbackInfo& info) {
}
// Calculate colour distance
maxColourDistance = image1.dE00(image2).max();
} catch (vips::VError const &err) {
} catch (std::runtime_error const &err) {
throw Napi::Error::New(env, err.what());
}

View File

@@ -36,6 +36,7 @@ describe('AVIF', () => {
density: 72,
depth: 'uchar',
format: 'jpeg',
mediaType: 'image/jpeg',
hasAlpha: false,
hasProfile: false,
// 32 / (2048 / 858) = 13.40625
@@ -64,6 +65,7 @@ describe('AVIF', () => {
compression: 'av1',
depth: 'uchar',
format: 'heif',
mediaType: 'image/avif',
hasAlpha: false,
hasProfile: false,
height: 26,
@@ -93,6 +95,7 @@ describe('AVIF', () => {
compression: 'av1',
depth: 'uchar',
format: 'heif',
mediaType: 'image/avif',
hasAlpha: false,
hasProfile: false,
height: 24,
@@ -119,6 +122,7 @@ describe('AVIF', () => {
compression: 'av1',
depth: 'uchar',
format: 'heif',
mediaType: 'image/avif',
hasAlpha: false,
hasProfile: false,
height: 13,
@@ -148,6 +152,7 @@ describe('AVIF', () => {
compression: 'av1',
depth: 'uchar',
format: 'heif',
mediaType: 'image/avif',
hasAlpha: true,
hasProfile: false,
height: 300,
@@ -178,6 +183,7 @@ describe('AVIF', () => {
compression: 'av1',
depth: 'uchar',
format: 'heif',
mediaType: 'image/avif',
hasAlpha: false,
hasProfile: false,
height: 26,
@@ -236,6 +242,7 @@ describe('AVIF', () => {
void exif;
assert.deepStrictEqual(metadata, {
format: 'heif',
mediaType: 'image/avif',
width: 4096,
height: 800,
space: 'srgb',
@@ -259,6 +266,7 @@ describe('AVIF', () => {
const { size, ...pngMetadata } = await sharp(data).metadata();
assert.deepStrictEqual(pngMetadata, {
format: 'png',
mediaType: 'image/png',
width: 4096,
height: 800,
space: 'srgb',

View File

@@ -19,6 +19,7 @@ describe('Image metadata', () => {
sharp(fixtures.inputJpg).metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('jpeg', metadata.format);
assert.strictEqual('image/jpeg', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(2725, metadata.width);
assert.strictEqual(2225, metadata.height);
@@ -41,6 +42,7 @@ describe('Image metadata', () => {
sharp(fixtures.inputJpgWithExif).metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('jpeg', metadata.format);
assert.strictEqual('image/jpeg', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(450, metadata.width);
assert.strictEqual(600, metadata.height);
@@ -66,6 +68,7 @@ describe('Image metadata', () => {
const profile = icc.parse(metadata.icc);
assert.strictEqual('object', typeof profile);
assert.strictEqual('Generic RGB Profile', profile.description);
assert.strictEqual('image/jpeg', metadata.mediaType);
done();
});
});
@@ -92,6 +95,7 @@ describe('Image metadata', () => {
sharp(fixtures.inputTiff).metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('tiff', metadata.format);
assert.strictEqual('image/tiff', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(2464, metadata.width);
assert.strictEqual(3248, metadata.height);
@@ -111,6 +115,7 @@ describe('Image metadata', () => {
assert.strictEqual('undefined', typeof metadata.xmp);
assert.strictEqual('undefined', typeof metadata.xmpAsString);
assert.strictEqual('inch', metadata.resolutionUnit);
assert.strictEqual('image/tiff', metadata.mediaType);
done();
});
});
@@ -119,6 +124,7 @@ describe('Image metadata', () => {
sharp(fixtures.inputTiffMultipage).metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('tiff', metadata.format);
assert.strictEqual('image/tiff', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(2464, metadata.width);
assert.strictEqual(3248, metadata.height);
@@ -142,6 +148,7 @@ describe('Image metadata', () => {
sharp(fixtures.inputPng).metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('png', metadata.format);
assert.strictEqual('image/png', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(2809, metadata.width);
assert.strictEqual(2074, metadata.height);
@@ -166,6 +173,7 @@ describe('Image metadata', () => {
sharp(fixtures.inputPngTestJoinChannel).metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('png', metadata.format);
assert.strictEqual('image/png', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(320, metadata.width);
assert.strictEqual(240, metadata.height);
@@ -191,6 +199,7 @@ describe('Image metadata', () => {
sharp(fixtures.inputPngWithTransparency).metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('png', metadata.format);
assert.strictEqual('image/png', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(2048, metadata.width);
assert.strictEqual(1536, metadata.height);
@@ -225,6 +234,7 @@ describe('Image metadata', () => {
height: 32,
isPalette: false,
isProgressive: false,
mediaType: 'image/png',
space: 'b-w',
width: 32,
autoOrient: {
@@ -250,6 +260,7 @@ describe('Image metadata', () => {
height: 32,
isPalette: false,
isProgressive: false,
mediaType: 'image/png',
space: 'grey16',
width: 32,
autoOrient: {
@@ -263,6 +274,7 @@ describe('Image metadata', () => {
sharp(fixtures.inputWebP).metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('webp', metadata.format);
assert.strictEqual('image/webp', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(1024, metadata.width);
assert.strictEqual(772, metadata.height);
@@ -285,11 +297,12 @@ describe('Image metadata', () => {
sharp(fixtures.inputWebPAnimated)
.metadata()
.then(({
format, width, height, space, channels, depth,
format, mediaType, width, height, space, channels, depth,
isProgressive, pages, loop, delay, hasProfile,
hasAlpha
}) => {
assert.strictEqual(format, 'webp');
assert.strictEqual(mediaType, 'image/webp');
assert.strictEqual(width, 80);
assert.strictEqual(height, 80);
assert.strictEqual(space, 'srgb');
@@ -308,11 +321,12 @@ describe('Image metadata', () => {
sharp(fixtures.inputWebPAnimated, { pages: -1 })
.metadata()
.then(({
format, width, height, space, channels, depth,
format, mediaType, width, height, space, channels, depth,
isProgressive, pages, pageHeight, loop, delay,
hasProfile, hasAlpha
}) => {
assert.strictEqual(format, 'webp');
assert.strictEqual(mediaType, 'image/webp');
assert.strictEqual(width, 80);
assert.strictEqual(height, 720);
assert.strictEqual(space, 'srgb');
@@ -332,11 +346,12 @@ describe('Image metadata', () => {
sharp(fixtures.inputWebPAnimatedLoop3)
.metadata()
.then(({
format, width, height, space, channels, depth,
format, mediaType, width, height, space, channels, depth,
isProgressive, pages, loop, delay, hasProfile,
hasAlpha
}) => {
assert.strictEqual(format, 'webp');
assert.strictEqual(mediaType, 'image/webp');
assert.strictEqual(width, 370);
assert.strictEqual(height, 285);
assert.strictEqual(space, 'srgb');
@@ -355,6 +370,7 @@ describe('Image metadata', () => {
sharp(fixtures.inputGif).metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('gif', metadata.format);
assert.strictEqual('image/gif', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(800, metadata.width);
assert.strictEqual(533, metadata.height);
@@ -375,6 +391,7 @@ describe('Image metadata', () => {
sharp(fixtures.inputGifGreyPlusAlpha).metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('gif', metadata.format);
assert.strictEqual('image/gif', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(2, metadata.width);
assert.strictEqual(1, metadata.height);
@@ -395,11 +412,12 @@ describe('Image metadata', () => {
sharp(fixtures.inputGifAnimated)
.metadata()
.then(({
format, width, height, space, channels, depth,
format, mediaType, width, height, space, channels, depth,
isProgressive, pages, loop, delay, background,
hasProfile, hasAlpha
}) => {
assert.strictEqual(format, 'gif');
assert.strictEqual(mediaType, 'image/gif');
assert.strictEqual(width, 80);
assert.strictEqual(height, 80);
assert.strictEqual(space, 'srgb');
@@ -419,11 +437,12 @@ describe('Image metadata', () => {
sharp(fixtures.inputGifAnimatedLoop3)
.metadata()
.then(({
format, width, height, space, channels, depth,
format, mediaType, width, height, space, channels, depth,
isProgressive, pages, loop, delay, hasProfile,
hasAlpha
}) => {
assert.strictEqual(format, 'gif');
assert.strictEqual(mediaType, 'image/gif');
assert.strictEqual(width, 370);
assert.strictEqual(height, 285);
assert.strictEqual(space, 'srgb');
@@ -462,6 +481,7 @@ describe('Image metadata', () => {
it('File in, Promise out', (_t, done) => {
sharp(fixtures.inputJpg).metadata().then((metadata) => {
assert.strictEqual('jpeg', metadata.format);
assert.strictEqual('image/jpeg', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(2725, metadata.width);
assert.strictEqual(2225, metadata.height);
@@ -508,6 +528,7 @@ describe('Image metadata', () => {
const pipeline = sharp();
pipeline.metadata().then((metadata) => {
assert.strictEqual('jpeg', metadata.format);
assert.strictEqual('image/jpeg', metadata.mediaType);
assert.strictEqual(829183, metadata.size);
assert.strictEqual(2725, metadata.width);
assert.strictEqual(2225, metadata.height);
@@ -559,6 +580,7 @@ describe('Image metadata', () => {
const pipeline = sharp().metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('jpeg', metadata.format);
assert.strictEqual('image/jpeg', metadata.mediaType);
assert.strictEqual(829183, metadata.size);
assert.strictEqual(2725, metadata.width);
assert.strictEqual(2225, metadata.height);
@@ -583,6 +605,7 @@ describe('Image metadata', () => {
image.metadata((err, metadata) => {
if (err) throw err;
assert.strictEqual('jpeg', metadata.format);
assert.strictEqual('image/jpeg', metadata.mediaType);
assert.strictEqual('undefined', typeof metadata.size);
assert.strictEqual(2725, metadata.width);
assert.strictEqual(2225, metadata.height);
@@ -917,6 +940,7 @@ describe('Image metadata', () => {
.metadata()
.then(metadata => {
assert.strictEqual(metadata.format, 'tiff');
assert.strictEqual(metadata.mediaType, 'image/tiff');
assert.strictEqual(metadata.width, 317);
assert.strictEqual(metadata.height, 211);
assert.strictEqual(metadata.space, 'rgb16');
@@ -931,6 +955,7 @@ describe('Image metadata', () => {
const metadata = await sharp(fixtures.inputAvif).metadata();
assert.deepStrictEqual(metadata, {
format: 'heif',
mediaType: 'image/avif',
width: 2048,
height: 858,
space: 'srgb',
@@ -1014,6 +1039,7 @@ describe('Image metadata', () => {
const metadata = await sharp(fixtures.inputJpgLossless).metadata();
assert.deepStrictEqual(metadata, {
format: 'jpeg',
mediaType: 'image/jpeg',
width: 227,
height: 149,
space: 'srgb',

View File

@@ -145,6 +145,7 @@ describe('PNG', () => {
width: 68
},
format: 'png',
mediaType: 'image/png',
width: 68,
height: 68,
space: 'srgb',