wxPythonのwx.ImageとPython Imaging Libraryの変換方法
wxPythonで用意されているImageやBitmapをPython Imaging Libraryで使うにはどうすればいいのか?という話。
wxPythonはさまざまなフォーマットの画像を読み込めるので便利です。wx.ImageとPILを相互変換できるなら、
読み込んだwxImageをPython Imaging LibraryのImageに変換して、画像処理に使うことができます。
相互変換するための関数の例と、実際に作成したサンプルコードを紹介します。
wx.ImageからPILへの変換
newメソッドでpilの画像を入力画像と同サイズで作ります。wxImageのGetDataメソッドで取り出したRawデータを、pilのfromstringメソッドで取り込めばOKです。
#convert wx.Image to PIL Image def wxImageToPil(wximage): pil = Image.new('RGB', (wximage.GetWidth(), wximage.GetHeight())) pil.fromstring(wximage.GetData()) return pil
PILからwx.Imageへの変換
今度は逆にwxImageをEmptyImageメソッドで新たに作成します。
pilのtostringメソッドでRawデータを取り出したあと、wxImageのSetDataメソッドで書き込めばOKです。
#convert PIL Image to wx.Image def pilToImage(pil): wximage = wx.EmptyImage(pil.size[0], pil.size[1]) wximage.SetData(pil.convert('RGB').tostring()) return wximage
この二つの関数を使って画像処理アプリのひな形を作成してみます。
以前作ったImage Viewerのコードを使います。↓
wxPythonのwxImageで画像を表示する - white wheelsのメモ
画像の読み込みとPILへの変換
適当な画像sample.bmpを用意して、wxImageに読み込みます。ウインドウに表示するためにBitmapに変換し、さらに画像データを扱うためにPilに変換します。このときPILはframeのメンバとして持たせておきます。
#open and setup wx.Image wximage = wx.Image('sample.bmp') self.bitmap = wximage.ConvertToBitmap() #wxImage to Bitmap self.pilImage = wxImageToPil(wximage) #wxImage to pil
画像処理部分
メンバとして保持しているPILの画像に処理を行ったあと、wxImageにもどして、さらにBitmapに変換すると良いです。
グレースケールへの変換が下の例。
#------write codes for image processing here---# pil = self.pilImage.convert("L") #----------------------------------------------# wximage = pilToImage(pil) #pil to wxImage self.bitmap = wximage.ConvertToBitmap() #wxImage to Bitmap
以上でPILを使って画像処理を行うGUIアプリの土台が整いました。
左クリックでグレースケールに、右クリックで元の画像にするサンプルが下の例です。
import wx #wx.Image import Image #PIL #convert wx.Image to PIL Image def wxImageToPil(wximage): pil = Image.new('RGB', (wximage.GetWidth(), wximage.GetHeight())) pil.fromstring(wximage.GetData()) return pil #convert PIL Image to wx.Image def pilToImage(pil): wximage = wx.EmptyImage(pil.size[0], pil.size[1]) wximage.SetData(pil.convert('RGB').tostring()) return wximage class myFrame(wx.Frame): def __init__(self, parent, title): wx.Frame.__init__(self, parent, title=title) #event handling self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown) self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown) #open and setup wx.Image wximage = wx.Image('sample.bmp') self.bitmap = wximage.ConvertToBitmap() #wxImage to Bitmap self.pilImage = wxImageToPil(wximage) #wxImage to pil self.SetSize(wximage.GetSize()) def OnPaint(self, event=None): deviceContext = wx.PaintDC(self) deviceContext.Clear() deviceContext.SetPen(wx.Pen(wx.BLACK, 4)) deviceContext.DrawBitmap(self.bitmap, 0, 0, True) def OnMouseLeftDown(self, event): #------write codes for image processing here---# pil = self.pilImage.convert("L") #----------------------------------------------# wximage = pilToImage(pil) #pil to wxImage self.bitmap = wximage.ConvertToBitmap() #wxImage to Bitmap self.Refresh() def OnMouseRightDown(self, event): wximage = pilToImage(self.pilImage) #pil to wxImage self.bitmap = wximage.ConvertToBitmap() #wxImage to Bitmap self.Refresh() app = wx.App(False) frame = myFrame(None, "Image Converter") frame.Show() app.MainLoop()