あんまりPythonの世界のことは詳しくないんですが,いまのPythonってレガシーな2系を維持しつつ,3系に注力している,って感じなんですかね.
自分の作ってるプログラムの一部の挙動を,Pythonでスクリプト化したかったんですが,まぁどうせなら未来のあるPython3を使ってみようかと.
で,そのなかでFreeImageをPythonからたたく必要があったのですが,Python3で動かそうと思ったら若干大変でした.
FreeImageのサイトの説明には,
Thanks to it’s ANSI C interface, FreeImage is usable in many languages including C, C++, VB, C#, Delphi, Java and also in common scripting languages such as Perl, Python, PHP, TCL or Ruby.
って書いてあるんですが,これ要するに「Cインターフェース持ってるから~の言語から使用可能だよ!」ってだけでライブラリのメンテナが全ての言語へのバインドを提供しているわけじゃないんですね.なんか詐欺くさい書き方だなぁ.
FreeImageのソースに含まれているバインドはC++とC#だけです. だれかPython用のバインドを書いてないかなー,と思ったら一応あるようです → FreeImagePy
ただしこれはPython2用なので一部書き換えの必要がありました. やったことは,
- 2to3で変換
- タイプチェック
type(x) == ctypes.IntType
をisinstance(x, int)
に書き換え PyString_FromStringAndSize
をPyUnicode_FromStringAndSize
に書き換え
くらい.一応パッチと,パッチ当て済みのものを置いておきます.
もちろん,パスにFreeImage.dllが入ってないと動きません.
サンプルコード
色深度32bit,縦横512ピクセルの画像を作って白く塗りつぶしてPNG形式で保存するサンプルです.
import ctypes as C import FreeImagePy as FIP fi = FIP.freeimage() fi.Initialise(True) width = 512 height = 512 dib = fi.Allocate(width, height, 32) for y in range(height): for x in range(width): rgbq = FIP.RGBQUAD() rgbq.rgbRed = 255 rgbq.rgbGreen = 255 rgbq.rgbBlue = 255 rgbq.rgbReserved = 255 fi.SetPixelColor(dib,x,y,C.pointer(rgbq)) fi.FlipVertical(dib) fi.Save(FIP.FIF_PNG, dib, "test.png") fi.Unload(dib) fi.DeInitialise()
いまいちPythonの作法を知らないので戸惑いましたが,ポインタをとる場面ではctypes.POINTERというファクトリメソッドを使うようですね.
バインドされていない関数
どうもこのFreeImagePyってモジュール,あんまりメンテされているモノではないらしく いくつかFreeImageの関数が抜けてることもあるようです(まぁ,サイトに”A lot of function bound, but not all, sorry!”って書いてあるしね).
見つけた限りではFreeImage_FlipVertical
とかFreeImage_FlipHorizontal
が抜けていました.不足している関数を補うには,以下の手順が必要です.
FreeImagePy.py
にインターフェースメソッドを追加function_list.py
にDLL関数名を追加
たとえば,FreeImage_FlipVertical
/FreeImage_FlipHorizontal
の場合なら,
FreeImagePy.py
のFreeImageクラスにメソッドを追加して…
# Flip def FlipHorizontal(self, dib): return self.__lib.FlipHorizontal(dib) def FlipVertical(self, dib): return self.__lib.FlipVertical(dib)
function_list.py
のFUNCTION_LIST
リストに以下を追加します.
('FreeImage_FlipHorizontal', '@4'), ('FreeImage_FlipVertical', '@4')
各エントリの二個目はdumpbin /exports FreeImage.dll
で出てくるシンボル名の後ろに付いているやつのようです.3つめ以降は戻り値型のようですが詳細はよくわかりません.