6
5

More than 5 years have passed since last update.

Kivyのtextureでの画像表示の注意点

Posted at

Kivyで、textureを使って画像表示した際に、
なんか表示がうまく行かず、調べたら「これはひどい1」となったので、
今後のためにメモ

textureでの画像表示

textureでの画像表示は、sourceを使わず、textureを使う。
(textureで表示しようとしているので当たり前)

最初のソース(問題あり)

Pillow使ったので、こんな感じ。(参考->ここ2)
Pillowデータをtextureにした時の大事な点は、上下反転させる必要がある点みたい。
(ソースは、ほぼ前記事と一緒)

ImageApp.py
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()
image.kv
#: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_fix.py
  ~ 以上上記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を指定しましょう。

  1. ただの自分の無知 

  2. 何回もリンクすみません!ほんとお世話になります。 

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5