Moustikitos / tyf

Manipulate EXIF and IFD metadata.
19 stars 8 forks source link

XMP metadata #17

Closed Airyzf closed 1 year ago

Airyzf commented 1 year ago

How do I modify XMP-related metadata?

    'Xmp.MicrosoftPhoto.LensModel': 'test', 
    'Xmp.MicrosoftPhoto.CameraSerialNumber': 'CameraSerialNumber', 
    'Xmp.MicrosoftPhoto.DateAcquired': '20200606', 
    'Xmp.MicrosoftPhoto.FlashManufacturer': 'FlashManufacturer', 
    'Xmp.MicrosoftPhoto.FlashModel': 'FlashModel', # 闪光灯型号
    'Xmp.MicrosoftPhoto.LensManufacturer': 'LensManufacturer' 
Moustikitos commented 1 year ago

Hi,

XMP metadata is encoded in tag #700:

700: ("XMP", [3], None, "XML packet containing XMP metadata"),

I didn't dev something to decode or encode XMP metadata, but if you manage to do so you can add them into your pic using Tyf.

Moustikitos commented 1 year ago

The xmp metadata are stored in the Tyf object under xmp attribute. It is a Python ElementTree object. So you should be able to edit it and save it.

Airyzf commented 1 year ago

The xmp metadata are stored in the Tyf object under xmp attribute. It is a Python ElementTree object. So you should be able to edit it and save it.

Thank you for your reply. I can get the xmp data, but there is still no corresponding data in the picture after modification and saving.

Moustikitos commented 1 year ago

Make sure you modify the xmp attribute in place. The xmp attribute is actualy a shortcut pointing into the JpegFile instance (which is a list object).

>>> import Tyf
>>> im = Tyf.open("test/xmp-exif.jpg")
>>> list.__getitem__(im, 2)[-1] is im.xmp
True
>>> for e in im: print(e[1].__class__)
...
<class 'Tyf.TiffFile'>
<class 'bytes'>
<class 'xml.etree.ElementTree.Element'>
<class 'bytes'>
<class 'bytes'>
<class 'bytes'>
<class 'bytes'>
<class 'bytes'>
<class 'bytes'>

If you do something like :

>>> im.xmp = ...

You destroy the link.

Moustikitos commented 1 year ago

Consider this example:

>>> im = Tyf.open("test/xmp-exif.jpg")        
>>> im.xmp[0].remove(im.xmp[0][0])
>>> im.save("test.jpg")        
>>> im2 = Tyf.open("test.jpg")
>>> im = Tyf.open("test/xmp-exif.jpg")    
>>> len(Tyf.xmp.tostring(im2.xmp).decode())   
23304
>>> len(Tyf.xmp.tostring(im.xmp).decode())  
24265
Moustikitos commented 1 year ago

Hey,

I just pushed an update into the repo. You can set microsoft XMP tag:

>>> im = Tyf.open("test/xmp-exif.jpg")
>>> data = {
...     'LensModel': 'test', 
...     'CameraSerialNumber': 'CameraSerialNumber', 
...     'DateAcquired': '20200606',
...     'FlashManufacturer': 'FlashManufacturer',
...     'FlashModel': 'FlashModel', # 闪光灯型号
...     'LensManufacturer': 'LensManufacturer'
... }
>>> for k, v in data.items():
>>>     im.set_xmp(k, v, ns="http://ns.microsoft.com/photo/1.0")
>>> im.save("test.jpg")

You can install this version:

python -m pip install git+https://github.com/Moustikitos/tyf.git
Airyzf commented 1 year ago

Thank you very much for your guidance.

Moustikitos commented 1 year ago

👍 You're welcome !

Airyzf commented 1 year ago

image image

It seems that xmp is none

Moustikitos commented 1 year ago

Yes, xmp attribute returns None if no xmp segment found in the JPEG file.

Airyzf commented 1 year ago

There is no xmp data in the picture, and setting xmp data prompts None. How should I set it?

Moustikitos commented 1 year ago

Ok, i'll manage something to create the segment.

You can try:

>>> im._JpegFile__xmp_idx = 2
>>> list.insert(im, 2, (65505, Tyf.xmp.Element("{adobe:ns:meta/}xmpmeta")))
>>> Tyf.xmp.SubElement(im.xmp, "{" + Tyf.XmpNamespace["RDF"] + "}RDF")

Then you should be able to add the data.

Airyzf commented 1 year ago

image There is still an error.

Moustikitos commented 1 year ago

I updated the example above...

Moustikitos commented 1 year ago

I've pushed somme changes. You just have to use set_xmp and even if no xmp segment found it will create it to add the very first item. Tell me if it works so I can cleanly close this issue.

Airyzf commented 1 year ago

image Got an error when save image

Moustikitos commented 1 year ago

Try :

pythpn -m pip uinstall Tyf
python -m pip install git+https://github.com/Moustikitos/tyf.git

You don't need the custom code anymore. Only use set_xmp function

Airyzf commented 1 year ago
data = {
        'LensModel': 'test', 
        'CameraSerialNumber': 'CameraSerialNumber', 
        'DateAcquired': '20200606',
        'FlashManufacturer': 'FlashManufacturer',
        'FlashModel': 'FlashModel', # 闪光灯型号
        'LensManufacturer': 'LensManufacturer'
    }

Only the last attribute takes effect.

Moustikitos commented 1 year ago

Ok, redo the commands to upgrade Tyf, It should be okay now.

Airyzf commented 1 year ago

Great, set_xmp succeeded, but get_xmp couldn't get the data. Did self.xmp fail to load?

Moustikitos commented 1 year ago

Make sure to use the appropriate namespace.

>>> im = Tyf.open("test/xmp-exif.jpg")
unknown tag 42036 type [7]: <IFD tag Undefined:'Samsung Galaxy S7 Rear Camera'> ignored
>>> list.pop(im, 2)
(65505, <Element '{adobe:ns:meta/}xmpmeta' at 0x00000261507D5030>)
>>> del im._JpegFile__xmp_ns
>>> im.xmp
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "D:\Toons\Github\tyf\Tyf\__init__.py", line 411, in xmp
    raise XmpDataNotFound("no XMP segment found")
Tyf.XmpDataNotFound: no XMP segment found
>>> im.set_xmp("Comment", "test")  # default namespace EXIF used
<Element '{http://ns.adobe.com/exif/1.0/}Comment' at 0x00000261507C3790>
>>> im.set_xmp("Comment", "test", ns="MICROSOFT")  # namespace MICROSOFT used
<Element '{http://ns.microsoft.com/photo/1.0}Comment' at 0x00000261507C3880>
>>> im.get_xmp("Comment", ns="MICROSOFT")     
<Element '{http://ns.microsoft.com/photo/1.0}Comment' at 0x00000261507C3880>
>>> im.get_xmp("Comment")      
<Element '{http://ns.adobe.com/exif/1.0/}Comment' at 0x00000261507C3790>
>>> im.get_xmp("Comment").text
'test'
Airyzf commented 1 year ago

Yes, the namespace problem, thank you very much.

Moustikitos commented 1 year ago

👍