【Python】写真のxmpタグの読み書き

### はじめに

写真のJPGファイルに、撮影日時や場所などを記録することができます。ドローン等で撮影された写真にタグ情報が書かれていることがあります。それらは一般的なフォーマットに従って記録されているようです。それらを読み書きしたいのが目的です。

GPS Exif については多くの記述があります。なので、ここでは情報が少ないと思われる xmp についてメモしておきます。なお、読むことはできるのですが、書くところはうまくできていません。(涙)


## 準備: xmp-toolkit のインストール

### XMPとは

どうやら、Adobe が定義し、各ファイルにXML形式のテキストで情報をファイルのヘッダに加えるために用いていたようです。詳しくは分かりません。^^;)

なので、例えば、less コマンドで見ると、テキストのXMLの部分はそのまま読めます。
おじさんはLinux環境(WSL)ですが、
- less でファイルを開き
- 「binaryだけど開くか」と聞かれるのでYes とし
- xml という文字列を検索する(スラッシュ xml リターン）と、

```xml

<x:xmpmeta xmlns:x="adobe:ns:meta/">
 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <rdf:Description rdf:about="DJI Meta Data"
    xmlns:tiff="http://ns.adobe.com/tiff/1.0/"
    xmlns:exif="http://ns.adobe.com/exif/1.0/"
    xmlns:xmp="http://ns.adobe.com/xap/1.0/"
    xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:crs="http://ns.adobe.com/camera-raw-settings/1.0/"
    xmlns:drone-dji="http://www.dji.com/drone-dji/1.0/"
   xmp:ModifyDate="2018-12-14"
   xmp:CreateDate="2018-12-14"
   tiff:Make="DJI"
   tiff:Model="FC6310R"
   dc:format="image/jpg"
   drone-dji:AbsoluteAltitude="+255.92"
   ...
```
のように見えます。これらの情報を読み書きしたい、というのが目的です。

### python では

便利なツールはもちろん存在します。

```
python3 -m pip install python-xmp-toolkit
```

Adobe からXMP-Toolkit-SDKがソースごと公開もされています。組み込みやスマホアプリで利用できるのかな。
https://github.com/adobe/XMP-Toolkit-SDK

# xmp のタグの値を読む

使い方は[python-xmp-toolkit のDoc](https://python-xmp-toolkit.readthedocs.io/en/latest/using.html)に書かれていて、それをフォローするだけで問題なかったです。メモしておきます。

## ファイルを読む

```python:read_xmp01.py
from libxmp import XMPFiles
xmpfile = XMPFiles( file_path="./100_0020_0001.JPG", open_forupdate=True )
xmp = xmpfile.get_xmp()
```
エラーが出なければ読めています。^^;) いろいろxmp の中身を調べることができます。


## 値の取得
先のサンプルでは

tiff:Make="DJI"

という行がありました。これを "tiff:Make" というkey に対して value である　"DJI"を直接取得したい。そのためには、２ステップ必要です。

### namespace の取得

まず、tiff のnamespace (URI)を取得します。

```python
In[]: xmp.get_namespace_for_prefix("tiff")
Out[]: 'http://ns.adobe.com/tiff/1.0/'
```
あらかじめadobe が定義されているnamespace もありこれはライブラリからも参照できます。

```python
In []: libxmp.consts.XMP_NS_EXIF
Out[]: 'http://ns.adobe.com/exif/1.0/'
```


変数名は直接[ソース](https://github.com/python-xmp-toolkit/python-xmp-toolkit/blob/master/libxmp/consts.py)の "Common Namespaces" をみて知ることもできます。

### property を取得する

tiff:Make というタグの値を読むには、さきほどのtiffに対応するnamespace を指定してあげます。

```python
In []: xmp.get_property(xmp.get_namespace_for_prefix('tiff'),'Make')
Out[]: 'DJI'
```

namespace内にそのキーワードがあるかを事前に確認することで、エラーを未然に防げます。

```python
In []: xmp.does_property_exist(xmp.get_namespace_for_prefix('tiff'),'TEST')
Out[]: False
```

## 書く

正確には「書き換える」ができる「はず」なのですが、実は。。。

まず、xmp の値をsetします。

```python
In []: xmp.set_property(xmp.get_namespace_for_prefix('tiff'),'Make', 'some/makers')
In []: xmp.get_property(xmp.get_namespace_for_prefix('tiff'),'Make')
Out[]: 'some/makers'
```

ファイルに書くには、xmpfileにput して file を close する必要があるようです。

```python
In []: if xmpfile.can_put_xmp(xmp):
  ...:     xmpfile.put_xmp(xmp)
  ...:     xmpfile.close_file()
```
で良いはずなのですが。。。結果は正しく書き換えられていませんでした。手順が違うのかバグなのか分かりませんが、とりあえずここまでメモしておきます。実行時にエラーは発生しません。

### メモ

とりあえず読むことだけできる、という状態でした。以下自分の課題：

- 各 namespace にあるタグを事前にすべて取得できるか？
- 書き込みの動作確認

以上。(2020/08/08)