ImageMagickのconvert
コマンドでaiをpngに変換すると、冪等になりません。変換結果をGitなどで保存している場合、毎回変わるので面倒です。aiファイルに変化があった時だけ変換結果のpngも変わるようにしたいです。
環境
libpngのバージョンによって結果が異なったので、OS XとDebianの2種類の環境で検証しました。
OS X Yosemite
- ImageMagick 6.8.9-8
- libpng 1.6.20
$ convert --version
Version: ImageMagick 6.8.9-8 Q16 x86_64 2014-10-23 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC Modules
Delegates: bzlib freetype jng jpeg ltdl lzma png zlib
$ convert -list format | grep PNG
JNG* PNG rw- JPEG Network Graphics
MNG* PNG rw+ Multiple-image Network Graphics (libpng 1.6.13,1.6.20)
PNG* PNG rw- Portable Network Graphics (libpng 1.6.13,1.6.20)
See http://www.libpng.org/ for details about the PNG format.
PNG00* PNG rw- PNG inheriting bit-depth and color-type from original
PNG24* PNG rw- opaque or binary transparent 24-bit RGB (zlib 1.2.5)
PNG32* PNG rw- opaque or transparent 32-bit RGBA
PNG48* PNG rw- opaque or binary transparent 48-bit RGB
PNG64* PNG rw- opaque or transparent 64-bit RGBA
PNG8* PNG rw- 8-bit indexed with optional binary transparency
(libpng 1.6.13,1.6.20)
という表記は、1.6.13でコンパイルされ、1.6.20の共有ライブラリを使っているという意味だそうです。
Debian Jessie
- ImageMagick 6.8.9-9
- libpng 1.2.50
$ convert --version
Version: ImageMagick 6.8.9-9 Q16 x86_64 2015-01-05 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC Modules OpenMP
Delegates: bzlib djvu fftw fontconfig freetype jbig jng jpeg lcms lqr ltdl lzma openexr pangocairo png tiff wmf x xml zlib
$ convert -list format | grep PNG
JNG* PNG rw- JPEG Network Graphics
MNG* PNG rw+ Multiple-image Network Graphics (libpng 1.2.50)
PNG* PNG rw- Portable Network Graphics (libpng 1.2.50)
See http://www.libpng.org/ for details about the PNG format.
PNG00* PNG rw- PNG inheriting bit-depth and color-type from original
PNG24* PNG rw- opaque or binary transparent 24-bit RGB (zlib 1.2.8)
PNG32* PNG rw- opaque or transparent 32-bit RGBA
PNG48* PNG rw- opaque or binary transparent 48-bit RGB
PNG64* PNG rw- opaque or transparent 64-bit RGBA
PNG8* PNG rw- 8-bit indexed with optional binary transparency
結論
とりあえず結論から。
OS X (libpng 1.6.20) の環境では、-strip
オプションを使うとPNGに埋め込まれるメタ情報を削除できます。
$ convert -density 300 -strip original.ai converted.png
他のメタ情報は残し、タイムスタンプだけを取り除きたい場合は以下のように+set
オプションを使うこともできます。
$ convert -density 300 +set date:create +set date:modify original.ai converted.png
Debian (libpng 1.2.50) の環境では、これらの方法だとtIME
チャンクが残ってしまったので、以下のようにすると取り除くことができました。
$ convert -density 300 -define png:exclude-chunk=tEXt,zTXt,tIME original.ai converted.png
事象の確認
OS X (libpng 1.6.20) の環境で、時間を置いて2つのファイルを生成します。
$ convert -density 300 original.ai old.png
$ # 時間を置いてから
$ convert -density 300 original.ai new.png
ファイルサイズは同じですが、diff
を取ると異なっていることがわかります。
$ ll *.png
-rw-r--r-- 1 orange staff 25197 1 24 15:38 new.png
-rw-r--r-- 1 orange staff 25197 1 24 15:38 old.png
$ diff old.png new.png
Binary files old.png and new.png differ
diff
コマンドではバイナリの詳しい比較ができないので、xxd
でHex形式に変換して差分を取ります。
$ xxd old.png old.hex
$ xxd new.png new.hex
$ diff new.hex old.hex
1566,1567c1566,1567
< 00061d0: 3454 3135 3a33 383a 3235 2b30 393a 3030 4T15:38:25+09:00
< 00061e0: b867 4a97 0000 0025 7445 5874 6461 7465 .gJ....%tEXtdate
---
> 00061d0: 3454 3135 3a33 383a 3230 2b30 393a 3030 4T15:38:20+09:00
> 00061e0: ea5f 6530 0000 0025 7445 5874 6461 7465 ._e0...%tEXtdate
1569,1570c1569,1570
< 0006200: 3234 5431 353a 3338 3a32 352b 3039 3a30 24T15:38:25+09:0
< 0006210: 30c9 3af2 2b00 0000 2074 4558 7470 6466 0.:.+... tEXtpdf
---
> 0006200: 3234 5431 353a 3338 3a32 302b 3039 3a30 24T15:38:20+09:0
> 0006210: 309b 02dd 8c00 0000 2074 4558 7470 6466 0....... tEXtpdf
タイムスタンプらしきものが埋め込まれており、これが異なっていることがわかります。
hexファイルを開いてみると、ファイルの末尾にtEXt
チャンクとして作成日時 (date:create
) と更新日時 (date:modify
) が埋め込まれています。
...
00061a0: 02bf 6bfa 0000 0040 1ffd ffe7 d465 a21a ..k....@.....e..
00061b0: 5fe2 4c00 0000 2574 4558 7464 6174 653a _.L...%tEXtdate:
00061c0: 6372 6561 7465 0032 3031 362d 3031 2d32 create.2016-01-2
00061d0: 3454 3135 3a33 383a 3235 2b30 393a 3030 4T15:38:25+09:00
00061e0: b867 4a97 0000 0025 7445 5874 6461 7465 .gJ....%tEXtdate
00061f0: 3a6d 6f64 6966 7900 3230 3136 2d30 312d :modify.2016-01-
0006200: 3234 5431 353a 3338 3a32 352b 3039 3a30 24T15:38:25+09:0
0006210: 30c9 3af2 2b00 0000 2074 4558 7470 6466 0.:.+... tEXtpdf
0006220: 3a48 6952 6573 426f 756e 6469 6e67 426f :HiResBoundingBo
0006230: 7800 3531 3578 3233 342b 302b 301e fd8f x.515x234+0+0...
0006240: fe00 0000 1474 4558 7470 6466 3a56 6572 .....tEXtpdf:Ver
0006250: 7369 6f6e 0050 4446 2d31 2e33 2053 06ac sion.PDF-1.3 S..
0006260: bf00 0000 0049 454e 44ae 4260 82 .....IEND.B`. `.
Debian (libpng 1.2.50) の環境で同様に比較すると、これらに加えてtIME
チャンクが異なっていることがわかります。
$ diff <(xxd debian_old.png) <(xxd debian_new.png)
155,156c155,156
< 00009a0: 0000 0007 7449 4d45 07e0 0118 062d 0bc1 ....tIME.....-..
< 00009b0: 2818 3700 0063 bc49 4441 5478 daed dd3b (.7..c.IDATx...;
---
> 00009a0: 0000 0007 7449 4d45 07e0 0118 062d 0fc6 ....tIME.....-..
> 00009b0: 45dc 2e00 0063 bc49 4441 5478 daed dd3b E....c.IDATx...;
1755c1755
< 0006da0: 3130 2b30 303a 3030 e5d8 3ed2 0000 0025 10+00:00..>....%
---
> 0006da0: 3134 2b30 303a 3030 1197 1ac1 0000 0025 14+00:00.......%
1758c1758
< 0006dd0: 3a31 302b 3030 3a30 3094 8586 6e00 0000 :10+00:00...n...
---
> 0006dd0: 3a31 342b 3030 3a30 3060 caa2 7d00 0000 :14+00:00`..}...
なお、pngcheck
コマンドを使うと以下のようにチャンクの値を確認できます。
$ pngcheck -vtc debian_old.png
File: debian_old.png (28213 bytes)
chunk IHDR at offset 0x0000c, length 13
2146 x 975 image, 8-bit grayscale, non-interlaced
chunk iCCP at offset 0x00025, length 2340
profile name = icc, compression method = 0 (deflate)
compressed profile = 2335 bytes
chunk cHRM at offset 0x00955, length 32
White x = 0.3127 y = 0.329, Red x = 0.64 y = 0.33
Green x = 0.3 y = 0.6, Blue x = 0.15 y = 0.06
chunk bKGD at offset 0x00981, length 2
gray = 0x00ff
chunk pHYs at offset 0x0098f, length 9: 300x300 pixels/unit (1:1)
chunk tIME at offset 0x009a4, length 7: 24 Jan 2016 06:45:11 UTC
chunk IDAT at offset 0x009b7, length 25532
zlib: deflated, 32K window, maximum compression
chunk tEXt at offset 0x06d7f, length 37, keyword: date:create
2016-01-24T06:45:10+00:00
chunk tEXt at offset 0x06db0, length 37, keyword: date:modify
2016-01-24T06:45:10+00:00
chunk tEXt at offset 0x06de1, length 32, keyword: pdf:HiResBoundingBox
515x234+0+0
chunk tEXt at offset 0x06e0d, length 20, keyword: pdf:Version
PDF-1.3
chunk IEND at offset 0x06e2d, length 0
No errors detected in debian_old.png (12 chunks, 98.7% compression).
調査
適当にググると以下のページがヒットします。
Getting ImageMagick convert to not write out extra info - Stack Overflow
http://stackoverflow.com/questions/13577280/getting-imagemagick-convert-to-not-write-out-extra-info
解決策1:-stripオプションを使う
$ convert -density 300 -strip original.ai old_without_date.png
$ # 時間を置いて
$ convert -density 300 -strip original.ai new_without_date.png
$ diff old_without_date.png new_without_date.png
diff
の結果から差分がないことがわかります。
hexファイルに変換してファイル末尾を見てみると、tEXt
チャンクが存在しません。
0006400: 9fcb 6417 1d27 ba78 7ebd 4ea3 f145 5760 ..d..'.x~.N..EW`
0006410: 3c24 0600 4cd6 5f3a bd56 d9e7 75f6 2dc6 <$..L._:.V..u.-.
0006420: 5720 1412 0300 0078 4062 0000 000f fe1f W .....x@b......
0006430: dfcb 7ebb a432 7e04 0000 0000 4945 4e44 ..~..2~.....IEND
0006440: ae42 6082 .B`.
なお、-strip
は画像のメタ情報を取り除くオプションです。
strip the image of any profiles or comments.
解決策2:+setオプションを使う
$ convert -density 300 +set date:create +set date:modify original.ai old_without_date2.png
$ # 時間を置いて
$ convert -density 300 +set date:create +set date:modify original.ai new_without_date2.png
$ diff old_without_date2.png new_without_date2.png
同じようにdiff
の結果から差分がないことがわかります。
hexファイルに変換してファイル末尾を見てみると、pdf:HiResBoundingBox
というtEXt
チャンクは残っていますが、date:create
とdate:modify
は消えていることがわかります。
0006400: a274 cae2 7cc3 eb37 6501 bf48 0c00 9894 .t..|..7e..H....
0006410: 9fcb 6417 1d27 ba78 7ebd 4ea3 f145 5760 ..d..'.x~.N..EW`
0006420: 3c24 0600 4cd6 5f3a bd56 d9e7 75f6 2dc6 <$..L._:.V..u.-.
0006430: 5720 1412 0300 0078 4062 0000 000f fe1f W .....x@b......
0006440: dfcb 7ebb a432 7e04 0000 0020 7445 5874 ..~..2~.... tEXt
0006450: 7064 663a 4869 5265 7342 6f75 6e64 696e pdf:HiResBoundin
0006460: 6742 6f78 0035 3135 7832 3334 2b30 2b30 gBox.515x234+0+0
0006470: 1efd 8ffe 0000 0014 7445 5874 7064 663a ........tEXtpdf:
0006480: 5665 7273 696f 6e00 5044 462d 312e 3320 Version.PDF-1.3
0006490: 5306 acbf 0000 0000 4945 4e44 ae42 6082 S.......IEND.B`.
なお、+set
は画像の属性やプロパティを削除するためのオプションです。
Using the +set form of the option will either remove, or reset that setting to a default state, as appropriate.
解決策3: -defineオプションを使う
Debian (libpng 1.2.50) の環境では、解決策1, 2ではtIME
チャンクを取り除けませんでした。以下のように-define
オプションを使うとチャンクの種類を指定して取り除くことができます。
$ convert -density 300 -define png:exclude-chunk=tEXt,zTXt,tIME original.ai converted.png
なお、-strip
オプションは以下のオプションと同等とのことです。
-define png:exclude-chunk=EXIF,iCCP,iTXt,sRGB,tEXt,zCCP,zTXt,date
参考
- diff - How do I compare binary files in Linux? - Super User
- Portable Network Graphics - Wikipedia, the free encyclopedia
- Getting ImageMagick convert to not write out extra info - Stack Overflow
- ImageMagick: Command-line Options
- imagemagick - How to check libpng version - Stack Overflow
- What software can I use to read png metadata? - Super User