Kivyで、textureを使って画像表示した際に、
なんか表示がうまく行かず、調べたら「これはひどい1」となったので、
textureでの画像表示
textureでの画像表示は、sourceを使わず、textureを使う。
(textureで表示しようとしているので当たり前)
最初のソース(問題あり)
from kivy.app import App
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.widget import Widget
from kivy.graphics.texture import Texture
from PIL import Image
class ImageWidget(Widget):
image_texture = ObjectProperty(None)
image_src = StringProperty('')
def __init__(self, **kwargs):
super(ImageWidget, self).__init__(**kwargs)
filename = './image.png'
self.image_src = filename
self.image_texture = image_to_texture(filename)
pass
class ImageApp(App):
def __init__(self, **kwargs):
super(ImageApp, self).__init__(**kwargs)
self.title = 'Image Slide'
def build(self):
return ImageWidget()
def image_to_texture(filepath):
img = Image.open(filepath)
texture = Texture.create(size=img.size)
texture.blit_buffer(img.tobytes())
texture.flip_vertical()
return texture
if __name__ == '__main__':
app = ImageApp()
app.run()
#:kivy 1.10
<ImageWidget>:
canvas.before:
Color:
rgb: 1,1,1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size: root.size
orientation: 'vertical'
Label:
text: root.image_src
color: 0, 0, 0, 1
font_size: 20
size_hint_y: 0.1
Image:
size_hint_y: 0.9
allow_stretch: True
texture: root.image_texture
で、表示されると思っていた!
が、いざ表示してみると、何か表示されるけど、表示したい画像がなんかずれて表示されてる感じだった。
修正版ソース
表示された画像からして、画像データのformatの認識ミスっぽく見えたので、調べたところ、
format | |
---|---|
Pillowで読み込んだ画像 | RGBA |
Texture.create()で作ったtexture | RGBA |
あれ?あってんじゃん。。。
と思って、KivyのドキュメントのTextureのところを見たら、
create()のParametersには、
colorfmt: str, defaults to ‘rgba’
blit_buffer()のParametersには、
colorfmt: str, defaults to ‘rgb’
と書いてあるのを見つけた。
やられた。これか。ということで、修正したソースが以下。
~ 以上、上記ImageApp.py差分無しのため省略 ~
def image_to_texture(filepath):
img = Image.open(filepath)
texture = Texture.create(size=img.size)
texture.blit_buffer(img.tobytes(), colorfmt='rgba')
texture.flip_vertical()
return texture
~ 以下、上記ImageApp.py差分無しのため省略 ~
これで、無事、ちゃんとした画像が表示されました。
修正版ソースでは、colorfmt='rgba'
として固定してしまっていますが、
本来は、img.mode
で取得した値に対して、colorfmtを変更する処理を書いたほうがよさそうです。
にしても、
(同じモジュール内の同じようなパラメータの)デフォルト値が違うのはわかりずらい...
まぁ、textureを作成する元データとしては、RGBが多いからってことなのかもしれないが...
まとめ
- textureは、Texture.create()で作成する。
- デフォルトのTexture.create()で出来たtextureは、RGBA。
- textureにデータを渡すには、Texture.blit_buffer()を使用する。
- デフォルトのTexture.blit_buffer()が期待するformatは、RGB。
- Texture.blit_buffer()に渡すデータに合わせてcolorfmtを指定しましょう。