pyvips icon indicating copy to clipboard operation
pyvips copied to clipboard

Q: How to set XMP metadata

Open scossu opened this issue 5 years ago • 4 comments

I need to inject some XMP metadata into an image to be written to disk as (big)TIFF.

Some related functionality seems to be documented in the libvips header documentation but I'm missing a clear path on how to insert a simple property in pyvips.

E.g. if I try to use img.set('xmp:copyright', copy_str) I get an error that I need to define the gtype for the property, but if I want to use set_type I am not sure which value I shall use for my type (str).

I also see a VIPS-META-XMP-NAME constant is defined in libvips but It's not clear to me how to use it or how to access it in pyvips.

Any help is appreciated. s

scossu avatar Mar 21 '19 19:03 scossu

Hi @scossu, XMP is stored as a binary blob, confusingly, rather than as a string. For example:

john@yingna ~/pics $ python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyvips
>>> im = pyvips.Image.new_from_file("wtc.jpg")
>>> im.get_fields()
['width', 'height', 'bands', 'format', 'coding', 'interpretation', 'xoffset', 'yoffset', 'xres', 'yres', 'filename', 'vips-loader', 'jpeg-multiscan', 'jpeg-chroma-subsample', 'exif-data', 'resolution-unit', 'exif-ifd0-Orientation', 'exif-ifd0-XResolution', 'exif-ifd0-YResolution', 'exif-ifd0-ResolutionUnit', 'exif-ifd0-YCbCrPositioning', 'exif-ifd2-ExifVersion', 'exif-ifd2-ComponentsConfiguration', 'exif-ifd2-FlashPixVersion', 'exif-ifd2-ColorSpace', 'exif-ifd2-PixelXDimension', 'exif-ifd2-PixelYDimension', 'orientation', 'icc-profile-data']

So there's no xmp-data field, we have to make one:

>>> im.set_type(pyvips.GValue.blob_type, "xmp-data", b"my great xmp string")
>>> im.write_to_file("x.tif")

Then read back to verify:

>>> x = pyvips.Image.new_from_file("x.tif")
>>> x.get_fields()
['width', 'height', 'bands', 'format', 'coding', 'interpretation', 'xoffset', 'yoffset', 'xres', 'yres', 'filename', 'vips-loader', 'n-pages', 'icc-profile-data', 'xmp-data', 'resolution-unit', 'orientation']
>>> x.get("xmp-data")
b'my great xmp string'

jcupitt avatar Mar 22 '19 13:03 jcupitt

Makes sense. I realize that I have to compose the XMP blob manually or with some other tool.

Thanks for the pointers. I now see the pyvips.GValue enums in the code, but the autodoc command doesn't seem to carry them over in the documentation.

scossu avatar Mar 23 '19 00:03 scossu

I think we were unsure about what should be in the public API. Probably type_from_name would be a better thing to export, so you'd do:

im.set_type(pyvips.type_from_name('VipsBlob'), 'xmp-data', b'my great xmp string')

jcupitt avatar Mar 23 '19 10:03 jcupitt

IMHO enums have a more canonical form than strings, but you may have architectural reasons for using strings; either one should be fine as long as there is a list of the options documented.

scossu avatar Mar 23 '19 16:03 scossu