-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose IPTC and XMP in metadata if available #1079
Conversation
@lovell I didn't see references to the WIP branch like mentioned in Contribution guide, so I've created PR targeting master branch. Feel free to change target branch. |
d82dbc0
to
65f3c94
Compare
Oops, that was my bad with coverage - forgot to remove .only from test. |
Rebased and squashed. |
Hello, this looks great, thank you. Do you think it's worth adding an assertion that inspects the first byte/word of each Buffer to ensure their contents are as-expected too? Update: I'm happy for devDependencies to be added that can parse the metadata for use in the tests. |
@@ -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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jcupitt Was the use of IPCT (vs IPTC) in the VIPS_META_IPCT_NAME
naming intentional/historical?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh dear, no, just acronymical dyslexia, sorry. I'll fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 8.6 with jcupitt/libvips@77287a9
There's a #define so the wrong name will still work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rodger! Thanks for the quick fix @jcupitt ;)
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a smaller test image we could use? (Perhaps resize this one but maintain metadata?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, sorry. I will definitely resize it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@lovell I wanted to add some kind of IPTC parser, but I didn't find good implementation for nodejs, which is at least maintained. For use in my main job project I've ended up implementing the custom one (I need to be able to use streams). Not sure if I will be releasing that as independent npm package, but I will definitely think about adding here something like this https://github.com/devongovett/exif-reader/blob/master/index.js#L4 |
65f3c94
to
333765c
Compare
test/unit/metadata.js
Outdated
// IPTC | ||
assert.strictEqual('object', typeof metadata.iptc); | ||
assert.strictEqual(true, metadata.iptc instanceof Buffer); | ||
// XMP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given there's no well-maintained IPTC parser, perhaps we could add an assertion on the Buffer length?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can work for now. Thanks for the suggestion @lovell! I will add it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we also can test it by checking that buffer starts with Photoshop
word.
⌘ exiv2 -pS test/fixtures/Landscape_9.jpg
STRUCTURE OF JPEG FILE: test/fixtures/Landscape_9.jpg
address | marker | length | data
0 | 0xffd8 SOI
2 | 0xffe0 APP0 | 16 | JFIF............
20 | 0xffe1 APP1 | 18835 | Exif..II*...............z......
18857 | 0xffe1 APP1 | 12497 | http://ns.adobe.com/xap/1.0/.<?x
31356 | 0xffed APP13 | 18252 | Photoshop 3.0.8BIM..............
49610 | 0xffe2 APP2 | 2444 | ICC_PROFILE......|lcms.0..mntrRG chunk 1/1
52056 | 0xffdb DQT | 67
52125 | 0xffdb DQT | 67
52194 | 0xffc0 SOF0 | 17
52213 | 0xffc4 DHT | 28
52243 | 0xffc4 DHT | 67
52312 | 0xffc4 DHT | 27
52341 | 0xffc4 DHT | 49
52392 | 0xffda SOS
test/unit/metadata.js
Outdated
assert.strictEqual(true, metadata.iptc instanceof Buffer); | ||
// XMP | ||
assert.strictEqual('object', typeof metadata.xmp); | ||
assert.strictEqual(true, metadata.xmp instanceof Buffer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
XMP is XML-ish so perhaps an assertion that the Buffer starts with <?xpacket
will be enough here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've went through specs and it looks like <?xpacket will not be enough... I may be wrong though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the image I added for tests buffer definitely doesn't start from <?xpacket
. exiv2 -pS ...
shows that there are two APP1 markers. One is used by EXIF. The other one looks close to what we want:
⌘ exiv2 -pS test/fixtures/Landscape_9.jpg
STRUCTURE OF JPEG FILE: test/fixtures/Landscape_9.jpg
address | marker | length | data
0 | 0xffd8 SOI
2 | 0xffe0 APP0 | 16 | JFIF............
20 | 0xffe1 APP1 | 18835 | Exif..II*...............z......
18857 | 0xffe1 APP1 | 12497 | http://ns.adobe.com/xap/1.0/.<?x
31356 | 0xffed APP13 | 18252 | Photoshop 3.0.8BIM..............
49610 | 0xffe2 APP2 | 2444 | ICC_PROFILE......|lcms.0..mntrRG chunk 1/1
52056 | 0xffdb DQT | 67
52125 | 0xffdb DQT | 67
52194 | 0xffc0 SOF0 | 17
52213 | 0xffc4 DHT | 28
52243 | 0xffc4 DHT | 67
52312 | 0xffc4 DHT | 27
52341 | 0xffc4 DHT | 49
52392 | 0xffda SOS
So http://ns.adobe.com/xap/1.0/
buffer header may work for tests. But even with this it looks like metadata.xmp
buffer is wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that byte length of both xmp
and iptc
property returned are equal. And content looks similar. Seems like we don't get appropriate buffers.
333765c
to
5e95688
Compare
@lovell I've added tests for buffer length for both |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello, the tests are failing as the ICC blob is erroneously being used - I've added a couple of comments inline.
src/metadata.cc
Outdated
// IPTC | ||
if (image.get_typeof(VIPS_META_IPCT_NAME) == VIPS_TYPE_BLOB) { | ||
size_t iptcLength; | ||
void const *iptc = image.get_blob(VIPS_META_ICC_NAME, &iptcLength); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- void const *iptc = image.get_blob(VIPS_META_ICC_NAME, &iptcLength);
+ void const *iptc = image.get_blob(VIPS_META_IPTC_NAME, &iptcLength);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lovell fixed. Tests passing locally. Waiting for CI
src/metadata.cc
Outdated
// XMP | ||
if (image.get_typeof(VIPS_META_XMP_NAME) == VIPS_TYPE_BLOB) { | ||
size_t xmpLength; | ||
void const *xmp = image.get_blob(VIPS_META_ICC_NAME, &xmpLength); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- void const *xmp = image.get_blob(VIPS_META_ICC_NAME, &xmpLength);
+ void const *xmp = image.get_blob(VIPS_META_XMP_NAME, &xmpLength);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh, silly me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lovell fixed. Tests passing locally. Waiting for CI
5e95688
to
47ff8c0
Compare
47ff8c0
to
99c49f3
Compare
Added one more test for
|
@lovell strange failure in AppVayor |
Brilliant, thank you Oleg, this will be in v0.19.0. |
Thanks you guys rock! Will try later. |
Closes #904