▲ Software Menu



m256 PerlMagick Composite Utility

Last Update : 2007/02/28

目次


ソフトの説明

Perl + Tkモジュール + Image-magick(PerlMagick)モジュールを利用して、連番画像ファイル(png/bmp/tga/jpeg)を画像合成するPerlスクリプトです。

※ WindowsXP Home SP2 + ActivePerl v5.8.8 build 819 で動作確認しています。

[ top ]

Screen Shot

Screen Shot
[ top ]

動作に必要な環境

このスクリプトはPerlで書かれています。Perlがインストールされた環境が必要です。また、

を利用していますので、それらのモジュールも必要になります。

Windows を使っているなら、ActivePerl をインストールすれば、Tkモジュールが標準で入っているようです。ActiveStateのサイトからダウンロード・インストールしてください。(ActivePerlのインストールの仕方は、ネット上のあちこちで詳しく解説されているので、そちらを参考にしてください。)

また、Windows版のImageMagickをインストールすれば、インストール途中で PerlMagick をインストールするかどうかのチェック項目が出てきます。

[ top ]

インストール・起動方法

このテキストファイル m256pmcu_pl.txtを適当なディレクトリに保存して、 m256pmcu.pl とファイル名を変更してください。(違うファイル名にしても構いません。拡張子が「.pl」ならいいはずです。)

[ top ]

アンインストール

m256pmcu.pl を削除するだけです。

[ top ]

起動方法

[ top ]

操作方法

上から順に、

を指定します。ファイル名入力欄の左側にある「select」ボタンを押すとファイル選択ウインドウが開きます。

「Composite Preview」で合成結果をプレビュー表示します。連番ファイルを指定している場合は、「Frame」の「Preview」で指定されたフレームを、合成・プレビュー表示します。

「Composite Execute」で画像を合成・ファイル出力します。処理が成功したかどうかは、ウインドウ下部のステータス部分に表示されます。

合成画像は、ただファイル出力されるだけで、プレビュー表示はされません。
※ プレビュー表示をする為に、3つほど、作業用ファイル(.ppmファイル)を作成しています。スクリプト終了時にそれら作業用ファイルを削除してはいますが、万が一何かしらの動作不具合が起きてそれらファイルが残ってしまった場合、手動で削除してしまって構いません。作業用ファイルは、スクリプトの置いてあるディレクトリに作成されるはずですが、スクリプト中の該当個所にディレクトリ名を記述することで明示的に指定することもできます。
[ top ]

補足

[ top ]

Download

スクリプトファイルはこちら → m256pmcu_pl.txt v0.03

[ top ]

開発環境

WindowsXP Home SP2 + ActivePerl v5.8.8 build 819 + Tk モジュール + ImageMagick(PerlMagick) モジュール

[ top ]

履歴

2007/02/28 v0.03 公開。ActivePerl v5.8.8 build 819 でプレビュー画像が表示できなかった不具合を修正。
2003/03/16 v0.02 公開。
	  
[ top ]

作成にあたってのメモ

作成過程やハマった点について記録を残しておきます。Perl/TkやImage-magick(PerlMagick)関連のドキュメントは比較的少ないように見受けられますし。何かしら参考になる部分があれば幸いです。また、事実誤認等あれば指摘してください。修正しておきます。



2003/03/11

PerlにImage-Magick(PerlMagick)モジュールをインストール。ImageMagickユーティリティで出来る事は全て出来るようだ。これほど機能があるなら、ImageMagickユーティリティにCUIで指示を出すより、Perlから呼び出して処理をした方がいい。自由度が高くなる。試しにスクリプトを作成してみようか。


2003/03/13

ひたすらPerlMagickの勉強。各種オプションの前に$をつけて変数にしてしまったり、-が必要なところで書き忘れたり、あるいは不必要なところでつけてしまったり、=>を->と書いてしまったり、しょうもないミスばかりで時間を消費してしまった気がする。

それでもようやく、canvas widgetにImage-Magick(PerlMagick)で読み込んだ画像を表示することが出来た。これができないとプレビューが出来ない。肝はImageToBlob()だった。
しかし、処理速度の問題故に、テンポラリとなるppm画像ファイルを一度作成し、それを読み込む形で実装しなければならなかった点には悔いが残る。内部に画像データをストアしたままで実装しようとすると、なぜか表示までに時間がかかってしまう。xpmであれば Pixmap(-data=>〜)とすることでテンポラリファイルを作らずに済むが、表示されるまでにかなり待たされる。というよりxpmは、ファイルから読み込もうと内部で持とうとどちらも表示に時間がかかる。元々、アイコン表示用のフォーマットとして策定されたという話も見かけたので、大きな画像で利用するのは不適当なのであろうか。また、Photo widget利用において、「ppmフォーマットの-data指定は利用不可」とエラーが出てくるのにも参った。各種資料には、gif/ppm/pgmが指定できると書いてあり、ファイルからの読み込みであればたしかに3つとも利用できてはいるのだが。現時点のActivePerl+Tkにおいて、Photo widgetの-data指定はgifしか使えないのかもしれない。残念。

compositeのcompose指定でもハマった。compose=>$compose_typeと書いただけではだめで、compose=>"$compose_type" と書く必要がある。直接、compose=>'plus'と記述すれば動作するのに、変数を介すと動作しないので途方に暮れた。

composite時、opacityがどういった形で反映しているのか不明。色々弄ってみたが結果に変化無し。透明度を弄るパラメータかと思ったのだが違うようだ。どんな役割を持っているのだろう。あるいは特定条件下でのみ有効になる類のパラメータであろうか。

getOpenFile , getSaveFileの-initialdir指定だが、windows上で動作させる場合は、/を\にしてやる必要があるようだ。試しに、s/\//\\/g を加えてみたところ、たしかに指定ディレクトリを開く事が出来た。しかし、これをUNIX上で行うと逆に不具合が発生するだろう。利用OSを判別できる特殊変数等、Perlに存在していれば助かるのだが。


2003/03/14

ImageMagickのmogrifyでpng→bmp変換したら、「パラパラ漫画道avi生成ツール(to_avi)」「AviUtl」「Videomaid」では読めないbmpファイルが出力されてしまった。to_aviは画面真っ黒・フレーム下のほうでゴミがチラチラとしか見えない異常なaviを出力し、AviUtlは「ファイル読み込みに失敗」と言い、Videomaidは「画像サイズのヘッダ情報が異常」と言っている。さては異常なbmpなのかと思い、各種ビュアーで表示確認をしてみるもpngもbmpも問題無く表示されているし、imagemagickのidentifyで画像情報を確認してみてもそれらしい情報が表示されているようにしか見えない。これは推測だが、ImageMagickの各種画像フォーマット出力において、通常利用時においては無視したほうがいい過剰な情報まで生真面目に含めた出力をしているが故に、極一般的なWindows用フリーソフトの類では読み込む事が出来ない、等の理由が存在していたりはしないだろうか。しかし、仮にそういった問題が存在していたとしても、そもそも考えてみれば、単なるpng→bmp変換ならBTJ32等巷に溢れる変換ツールを使えばいいだけの話。指定も楽だし、得られる結果画像にも問題は無い。実際、BTJ32でpng→bmp変換した画像を読み込ませたところ、to_aviは問題無いaviを生成してくれた。

それにしても、png読み込みをサポートしてるフリーのavi生成ツールが存在しないのはHDD容量的には厳しい状況だ。とは言え、to_aviは連番png読み込みにも対応しているのだが、ImagMagickの出力したpngを読み込ませると異様な色合いのaviを出力してしまった。「ルイちゃんくLE」でpng画像内のガンマ値削除も試してみたが結果改善には繋がらず。

何にせよ、ImageMagickを介して出力した最終画像に対しては、何かしら別のツールでフォーマット変換してから利用したほうが良さそうではある。実際、ImageMagickの出力したpng画像も、BTJ32で読み込んでpngで再保存してみたところ、to_aviも正常なaviを出力した。

もしかすると、ImageMagickを用いたpng保存時に各種パラメータを明確に指定することでこの手の問題を回避できる可能性があるのかもしれない。もう少し調べてみよう。


2003/03/15

to_aviでImageMagickの出力したpngを読み込むと異常な色合いのaviを出力してしまう理由が判明。αチャンネル付pngをImageMagickが出力していたが故の不具合だと思われる。ImageMagickの出力時に、img->Set(matte=>'False') を指定してから出力するとαチャンネル情報を含まないpngを出力してくれるが、そうして出力したpngを使ったところ問題は起きなかった。ちなみに、img->Set(type=>'TrueColorMatte')ではなく、img->Set(type=>'TrueColor')でも同様の事が出来るだろうと推測したが、実験したところ予想は外れた。その指定はαチャンネルを付加するかどうかの設定には関係ないらしく、αチャンネル付pngが出力された。

BTJ32とImageMagickの出力pngを調べると、αチャンネル付加以外にも違いがある事がわかった。

BTJ32…ピクセルデータチャンクを32768byte毎に区切っている。ガンマ値を持たない。tpNgなる謎のチャンクを持つ。

ImageMagick…ピクセルデータチャンクを8192Byte毎に区切っている。ガンマ値を持つ。ガンマ値は0.4545(Windows標準の2.2)が指定されている。物理的ピクセルサイズ情報チャンクを持つ。

ImageMagickで出力した場合、BTJ32の出力したpngに比べ約2.5倍のファイルサイズになっている。チャンクが多数に分けられていることや、そもそもフィルタや圧縮率を適切に指定していない(指定方法がわからない)ことが響いているのだろう。と思ったが、調べてみたところ、ImageMagickにおいても圧縮率等は指定できるようだ。img->Set(quality=>75)といった形で指定する。
jpegの場合、単純に0〜100までの間で指定すればいい。デフォルトは75。0が最も画質が悪く、100が最も画質が良い。当然ファイル容量は、0=小/100=大、となる。
pngの場合、10の桁がzlibの圧縮レベル(おそらく1〜9を取るのだろう)で、1の桁がフィルタ種類の指定になっている。これもデフォルトでは75。フィルタ指定5は、quality指定が50を越えた場合に有効に働くとドキュメントには書かれている。試しに95で指定してみたところ、BTJ32の出力したpngより若干小さいファイル容量になった。それでいてピクセルデータチャンクは相変らず8192byte毎に分割されている。ピクセルデータチャンクを分割するか否かは、ファイル容量とはあまり関係ないらしい。何はともあれ、これでHDDを若干圧迫せずに済みそうではある。

連番pngファイルをcompositeすると、さすがにかなりの時間待たされる。その為少々マズイ状況になっている。現在、ファイル入力・composite・出力が全て終了するまでの処理を、Buttonを押した際に呼ばれるcallback関数内で行っている。その為、処理中はボタンが押されてグレーになったままで見栄えがよくない。また、万が一他のwidgetに対し行動を起こされたら動作が途中から変わってしまう可能性がある。(callback関数を呼ぶと他のwidgetに対する操作が全て無効になるような仕様実装であれば問題無いだろうが、そのあたりの動作はまだ把握できていない。)

できれば、呼び出した時の各種設定は保持したまま処理を行い、更に、操作中のユーザの混乱を避けるべく現在何ファイルまで処理したのかステータス部分に逐次表示したい。前者は、関数内で参照される設定値をローカル変数で確保するよう変更すれば済みそうだ。しかし、後者のような処理をしようとすると、callback関数内で別スレッド(子プロセス?)を生成し、バックグラウンドで処理させる必要性が出てくる。

であれば、Perlのforkを使って子プロセス生成ができないか。しかし、forkについて調べてみるも、Windows版Perl(ActivePerl)では動作しないとのこと。正確には、一応5.6.1でforkのエミュレーションを実現したらしいのだが、ドキュメントには、正規表現が正常に動作しなくなる可能性が高い、といった内容のバグ報告が記述されていた。自分が子プロセス内でさせようとしている処理は、頻繁に正規表現を使う。よろしくない状況だ。

となると、Perl/Tkのafterメソッドを使って実装するしか手は無さそうだ。


2003/03/16

ひとまずバックグラウンド処理は実装できたように思う。buttonのcallback関数の中から、$mw->after(xxx,callback_func)として、さらにcallback_funcの中で、まだ処理が終わってないフレームがあったら自分自身を一定時間後にcallすることで実現。
しかしそもそも、各widgetの表示更新を明示的に行えればこういった面倒な処理をしなくて済むような気もするのだが。しかしその方法について、手持ちの解説書、あるいはネット上で見かけた各種ドキュメント上に見つける事は出来なかった。なんとなく存在していそうな気もするのだがどうなのだろう。

せっかくそれらしいスクリプトが出来たので、スクリプトを利用してサンプルmpegムービー(204Kbyte)を作ってみた。背景、及び、オブジェクトの連番pngを、gimpの動画→パス移動で作成。また、blenderでパーティクル動画の連番tgaを作成。背景+オブジェクトを'Over'で合成し、更にパーティクルの画像を'plus'で合成。出来た連番png(αチャンネル無しで出力)を、to_aviに読み込ませて、aviを作成。それをTMPGEncで読み込み、容量削減の為にサイズを縮小させつつ、mpgに変換。

関係無いが、手前のオブジェクトがネタ的にマズイかもしれない。gimpで作りやすそうだったのでコレにしたが。gimpの球面デザイナーで球を作った後、別レイヤーにパスで黒線を描き、レイヤーコピーして白線に変換。位置をずらし、球の不透明部分で選択範囲を作成、余分な部分を削除して、レイヤー統合しただけ。

ひとまず、フリーのツールのみを使ってここまでできれば充分のような気もする。Perlというお手軽スクリプト言語(?)を利用して、画像に対し色々な処理が出来る事も判ったし。ムービー素材画像作成に対する可能性が自分の中では少し広がった感が。でも、こういった処理をするフリーのツールは既にどこかにありそう。このスクリプト自体の存在価値はあまりないのでは。まあ、勉強だから、いいか。



[ top ]


▲ Software Menu