12

Python 3 にいくつかの RGBA データがあり、余分なライブラリを使用せずに GTK3 ウィンドウに表示する画像を表示したいと考えています。

最初に試したPixbufのは、例のように のデータを編集することでした (http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-The-GdkPixbuf-Structure.html#put-pixel - 申し訳ありませんが、私は(C) ドキュメントではPixbuf.get_pixels(). ただし、これにより不変bytesオブジェクトが得られるため、明らかに機能しません。(gdk-pixbuf バグ レポート (668084、SO が許可してくれればリンクします) は同じ機能をカバーしていますが、その後少し変更されたに違いありません。)

次に、 を使用してデータから Pixbuf を作成しようとしましたPixbuf.new_from_data()が、これもバグがあります (gdk-pixbuf バグ 674691 を参照) (はい、コメント 3 の私です)。

それから私は Cairo を見ました:ImageSurface.create_for_dataこれを行う必要がありますが、何らかの理由でこれは Python 3 バインディングではまだ利用できません。(私はこれを Python 2 で試し、サーフェスを後で に変えてPixbufから でラップしましたがgtk.Image、うまくいきました。しかし、私は Python3 を使用しています (それでも、面倒です - 結局のところ、カイロはベクトル グラフィックス ライブラリです)。 )。

PIL を使用して画像を PNG ファイルに書き出し、それを Pixbuf に読み込むという参照をどこかで見つけましたが、これは恐ろしいことであり、余分なライブラリを使用し、Python 3 では PIL を使用できません。

それで...他の方法はありますか?

作業コード

Havokの答えに基づいて、これが実際の例です:

from array import array

from gi.repository import Gtk as gtk, GdkPixbuf

pixels = array('H')
for i in range(20):
    for j in range(20):
        px = (i < 10, j >= 10, (i < 10) ^ (j < 10))
        pixels.extend(65535 * c for c in px)

header = b'P6 20 20 65535 '
img_data = header + pixels

w = gtk.Window()
w.connect('delete-event', gtk.main_quit)
l = GdkPixbuf.PixbufLoader.new_with_type('pnm')
l.write(img_data)
w.add(gtk.Image.new_from_pixbuf(l.get_pixbuf()))
l.close()
w.show_all()
gtk.main()

編集:実際には、正確を期すために、ヘッダーに追加する前にリトルエンディアンシステムが必要になると思いますpixels.byteswap()(もちろん、これらの色には関係ありません)。

4

3 に答える 3

6

うわー、これは大変だろう、かなり難しい。

PIL も Cairo の ImageSurface.create_from_data() も Python 3 では使用できません。残りの唯一のオプションは GdkPixbuf を直接使用することですが、これは完璧な解決策ではありません。特にアルファ チャネルを使用することを期待しているためです。私の唯一の考えは、あなたがこれを使おうとすることです:

http://developer.gnome.org/gdk-pixbuf/stable/GdkPixbufLoader.html#gdk-pixbuf-loader-new-with-type

ここの最後で行ったように: Converting PIL GdkPixbuf

loader = GdkPixbuf.PixbufLoader.new_with_type('pnm')
loader.write(contents)
pixbuf = loader.get_pixbuf()
loader.close()

また、サポートされている型を確認してみてください。C ドキュメントに記載されている内容の PyGObject バージョンgdk_pixbuf_format_get_name()pnm 形式gdk_pixbuf_get_formats()では、アルファ チャネルはありません。

編集

PyGObject関数を見つけて、ドキュメントの目的で出力をここに投稿してください。

>>> from gi.repository import GdkPixbuf
>>> formats = GdkPixbuf.Pixbuf.get_formats()
>>> [f.get_name() for f in formats]
['GdkPixdata', 'ras', 'tiff', 'wmf', 'icns', 'ico', 'png', 'qtif', 
 'wbmp', 'gif', 'pnm', 'tga', 'ani', 'xbm', 'xpm', 'jpeg2000', 
 'pcx', 'jpeg', 'bmp', 'svg']
于 2012-09-15T07:13:49.507 に答える
3

gtk3 はインストールしていませんが、gtk2 では問題なく動作しました。

import gtk
import cairo


def main():
    window = gtk.Window(gtk.WINDOW_TOPLEVEL)
    window.set_title("Drawing Area")
    window.connect("destroy", lambda w:gtk.main_quit())

    sw = gtk.ScrolledWindow()
    area = Area()
    area.show()
    area.connect('expose-event', area.expose_handler)
    sw.add_with_viewport(area)
    window.add(sw)
    window.show_all()


class Area(gtk.DrawingArea):
    def __init__(self):
        super(Area, self).__init__()
        self.pixbuf = gtk.gdk.pixbuf_new_from_file("hard_drive_elements.png")

    def expose_handler(self, widget, event):
        cr = self.window.cairo_create()
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.set_source_rgb(1,1,1)
        cr.paint()
        cr.set_source_pixbuf(self.pixbuf, 0, 0)
        cr.paint()


if __name__ == "__main__":
    main()
    gtk.main()

Drawing_area_from_pixbuf

于 2012-09-14T19:28:59.280 に答える