mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Expose IPTC and XMP metadata when available (#1079)
This commit is contained in:
parent
8afcb16d8e
commit
c4df115948
@ -182,6 +182,8 @@ function clone () {
|
||||
* - `orientation`: Number value of the EXIF Orientation header, if present
|
||||
* - `exif`: Buffer containing raw EXIF data, if present
|
||||
* - `icc`: Buffer containing raw [ICC](https://www.npmjs.com/package/icc) profile data, if present
|
||||
* - `iptc`: Buffer containing raw IPTC data, if present
|
||||
* - `xmp`: Buffer containing raw XMP data, if present
|
||||
*
|
||||
* @example
|
||||
* const image = sharp(inputJpg);
|
||||
|
@ -41,7 +41,8 @@
|
||||
"Matt Parrish <matt.r.parrish@gmail.com>",
|
||||
"Matthew McEachen <matthew+github@mceachen.org>",
|
||||
"Jarda Kotěšovec <jarda.kotesovec@gmail.com>",
|
||||
"Kenric D'Souza <kenric.dsouza@gmail.com>"
|
||||
"Kenric D'Souza <kenric.dsouza@gmail.com>",
|
||||
"Oleh Aleinyk <oleg.aleynik@gmail.com>"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "rm -rf node_modules/ build/ vendor/ coverage/ test/fixtures/output.*",
|
||||
|
@ -81,6 +81,22 @@ class MetadataWorker : public Nan::AsyncWorker {
|
||||
memcpy(baton->icc, icc, iccLength);
|
||||
baton->iccLength = iccLength;
|
||||
}
|
||||
// IPTC
|
||||
if (image.get_typeof(VIPS_META_IPCT_NAME) == VIPS_TYPE_BLOB) {
|
||||
size_t iptcLength;
|
||||
void const *iptc = image.get_blob(VIPS_META_IPCT_NAME, &iptcLength);
|
||||
baton->iptc = static_cast<char *>(g_malloc(iptcLength));
|
||||
memcpy(baton->iptc, iptc, iptcLength);
|
||||
baton->iptcLength = iptcLength;
|
||||
}
|
||||
// XMP
|
||||
if (image.get_typeof(VIPS_META_XMP_NAME) == VIPS_TYPE_BLOB) {
|
||||
size_t xmpLength;
|
||||
void const *xmp = image.get_blob(VIPS_META_XMP_NAME, &xmpLength);
|
||||
baton->xmp = static_cast<char *>(g_malloc(xmpLength));
|
||||
memcpy(baton->xmp, xmp, xmpLength);
|
||||
baton->xmpLength = xmpLength;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
@ -123,6 +139,16 @@ class MetadataWorker : public Nan::AsyncWorker {
|
||||
New("icc").ToLocalChecked(),
|
||||
Nan::NewBuffer(baton->icc, baton->iccLength, sharp::FreeCallback, nullptr).ToLocalChecked());
|
||||
}
|
||||
if (baton->iptcLength > 0) {
|
||||
Set(info,
|
||||
New("iptc").ToLocalChecked(),
|
||||
Nan::NewBuffer(baton->iptc, baton->iptcLength, sharp::FreeCallback, nullptr).ToLocalChecked());
|
||||
}
|
||||
if (baton->xmpLength > 0) {
|
||||
Set(info,
|
||||
New("xmp").ToLocalChecked(),
|
||||
Nan::NewBuffer(baton->xmp, baton->xmpLength, sharp::FreeCallback, nullptr).ToLocalChecked());
|
||||
}
|
||||
argv[1] = info;
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,10 @@ struct MetadataBaton {
|
||||
size_t exifLength;
|
||||
char *icc;
|
||||
size_t iccLength;
|
||||
char *iptc;
|
||||
size_t iptcLength;
|
||||
char *xmp;
|
||||
size_t xmpLength;
|
||||
std::string err;
|
||||
|
||||
MetadataBaton():
|
||||
@ -52,7 +56,11 @@ struct MetadataBaton {
|
||||
exif(nullptr),
|
||||
exifLength(0),
|
||||
icc(nullptr),
|
||||
iccLength(0) {}
|
||||
iccLength(0),
|
||||
iptc(nullptr),
|
||||
iptcLength(0),
|
||||
xmp(nullptr),
|
||||
xmpLength(0) {}
|
||||
};
|
||||
|
||||
NAN_METHOD(metadata);
|
||||
|
BIN
test/fixtures/Landscape_9.jpg
vendored
Normal file
BIN
test/fixtures/Landscape_9.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 91 KiB |
1
test/fixtures/index.js
vendored
1
test/fixtures/index.js
vendored
@ -57,6 +57,7 @@ module.exports = {
|
||||
|
||||
inputJpg: getPath('2569067123_aca715a2ee_o.jpg'), // http://www.flickr.com/photos/grizdave/2569067123/
|
||||
inputJpgWithExif: getPath('Landscape_8.jpg'), // https://github.com/recurser/exif-orientation-examples/blob/master/Landscape_8.jpg
|
||||
inputJpgWithIptcAndXmp: getPath('Landscape_9.jpg'), // https://unsplash.com/photos/RWAIyGmgHTQ
|
||||
inputJpgWithExifMirroring: getPath('Landscape_5.jpg'), // https://github.com/recurser/exif-orientation-examples/blob/master/Landscape_5.jpg
|
||||
inputJpgWithGammaHoliness: getPath('gamma_dalai_lama_gray.jpg'), // http://www.4p8.com/eric.brasseur/gamma.html
|
||||
inputJpgWithCmykProfile: getPath('Channel_digital_image_CMYK_color.jpg'), // http://en.wikipedia.org/wiki/File:Channel_digital_image_CMYK_color.jpg
|
||||
|
@ -58,6 +58,23 @@ describe('Image metadata', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('JPEG with IPTC/XMP', function (done) {
|
||||
sharp(fixtures.inputJpgWithIptcAndXmp).metadata(function (err, metadata) {
|
||||
if (err) throw err;
|
||||
// IPTC
|
||||
assert.strictEqual('object', typeof metadata.iptc);
|
||||
assert.strictEqual(true, metadata.iptc instanceof Buffer);
|
||||
assert.strictEqual(18250, metadata.iptc.byteLength);
|
||||
assert.strictEqual(metadata.iptc.indexOf(Buffer.from('Photoshop')), 0);
|
||||
// XMP
|
||||
assert.strictEqual('object', typeof metadata.xmp);
|
||||
assert.strictEqual(true, metadata.xmp instanceof Buffer);
|
||||
assert.strictEqual(12495, metadata.xmp.byteLength);
|
||||
assert.strictEqual(metadata.xmp.indexOf(Buffer.from('http://ns.adobe.com/xap/1.0')), 0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('TIFF', function (done) {
|
||||
sharp(fixtures.inputTiff).metadata(function (err, metadata) {
|
||||
if (err) throw err;
|
||||
|
Loading…
x
Reference in New Issue
Block a user