CPANモジュールImagerでpngのコメントを取得できるようにする。

CPANモジュールのImagerにはpngファイルを扱う機能が実装されている。
しかし、ソースを読んでみるとpngファイルのテキストデータを保持する「tEXt」チャンクの情報を取得する方法が提供されていない。
正確に言うと pHYs チャンクのみ処理するようにしていて他のチャンク処理は実装されていない。
そこで今回、(自分用に。。。) tEXt チャンク(テキストデータ) をperl側から取得できるようにソースを書き換える。

まずはCPANからImagerソースを取得する。

$ dh-make-perl --cpan Imager
$ ls
Imager-0.75  libimager-perl_0.75.orig.tar.gz
$ cd Imager-0.75

pngファイルの処理を行っているのは png.c になる。
このソースの「get_png_tags」関数で Imager オブジェクトの tags 配列の配列に pHYs チャンクの値を設定しているので、ここに tEXt チャンクの値を設定する処理を実装する。
ソースは下記のように変更した。

static void get_png_tags(i_img *im, png_structp png_ptr, png_infop info_ptr) {
  png_uint_32 xres, yres;
  int unit_type;

+  png_textp text_ptr;
+  int num_text;
+
  i_tags_add(&im->tags, "i_format", 0, "png", -1, 0);
  if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) {
    mm_log((1,"pHYs (%d, %d) %d\n", xres, yres, unit_type));
    if (unit_type == PNG_RESOLUTION_METER) {
      i_tags_set_float2(&im->tags, "i_xres", 0, xres * 0.0254, 5); 
      i_tags_set_float2(&im->tags, "i_yres", 0, yres * 0.0254, 5); 
    }   
    else {
      i_tags_addn(&im->tags, "i_xres", 0, xres);
      i_tags_addn(&im->tags, "i_yres", 0, yres);
      i_tags_addn(&im->tags, "i_aspect_only", 0, 1);
    }
  }
+  if (png_get_text(png_ptr, info_ptr, &text_ptr, &num_text)) {
+    int i;
+    for (i = 0; i < num_text; i++) {
+      mm_log((1, "text %d %s %s %d\n",
+        i, text_ptr[i].key, text_ptr[i].text, text_ptr[i].text_length));
+      i_tags_add(&im->tags, text_ptr[i].key, 0, text_ptr[i].text, text_ptr[i].text_length, 0);
+    }
+  }
}

では実際に利用するためにビルド・インストールを行う。
まずは念のためバージョン番号をインクリメントする。

$ dch -i
+libimager-perl (0.75-2) unstable; urgency=low
+
+  * support for tEXt chunk of png 
+
+ -- hayashi <hayashi@deb1.1.168.192.in-addr.arpa>  Sun, 18 Jul 2010 23:46:18 +0900
+
libimager-perl (0.75-1) unstable; urgency=low

  * Initial Release.

 -- hayashi <hayashi@deb1.1.168.192.in-addr.arpa>  Sun, 18 Jul 2010 23:16:11 +0900

そしてビルド・インストール。

$ debuild -rfakeroot -uc -us
$ cd ../
$ sudo dpkg -i libimager-perl_0.75-2_i386.deb
$ dpkg -l libimager-perl
ii  libimager-perl  0.75-2          Perl extension for Generating 24 bit Images

では実際にperl側から使ってみる。
perl側の実装は下記のようにした。

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

use Imager;

my $img = Imager->new(file => "a.png");
my %tags = map @$_, $img->tags();
print Dumper(\%tags);

png の tEXt チャンク未対応の Imager だと

$VAR1 = {
          'i_format' => 'png'
        };

という結果だが png の tEXt チャンク対応の Imager だと

$VAR1 = {
          'Software' => 'Adobe ImageReady',
          'i_format' => 'png'
        };

と「Software」の値が取れている。

まとめ

CPANモジュールImagerはlibpngを利用してpngファイルをパースしたり変形したりいろいろできる。
扱えるファイルフォーマットが多い分、細かい部分の実装は後回しになっている感じがする。
libpngやImagerのソースを追うことで実際の処理が理解できてとても勉強になった。
ソースを読んでいくと意外に理解できることが分かったのでどんどん読んでブログにフィードバックしていこうと思う。
(自分の勉強のために。。。)