3

を使用してGtk.StatusIconいますが、一部のピクセルの色を変更したいです。これは、設定したい色を含む1x1ピクセルのPNGファイルをロードし、それをアイコンPixbufにコピーします。
これは機能しますが、すべての色に対して 1x1 ピクセルを作成する必要があるという明らかな欠点があるため、任意の色を使用することはできず、画像を作成した定義済みの色のみを使用できます。

ピクセルを任意の RGBA カラーに設定するにはどうすればよいですか?

私が現在使用しているコード(デモンストレーションのために単純化されています):

#!/usr/bin/env python

from gi.repository import Gtk, GLib, GdkPixbuf

def set_icon_cb(widget, data=None):
    set_icon(widget)

def set_icon(icon):
    fill_amount = 20
    img = GdkPixbuf.Pixbuf.new_from_file('./data/icons/battery.png')
    fill = GdkPixbuf.Pixbuf.new_from_file('./data/icons/green.png')

    for row_num, row in enumerate(zip(*(iter(img.get_pixels()),) *img.get_rowstride())):
        # Blank row
        if 255 not in row: continue

        for col_num, pixel in enumerate(zip(*(iter(row),) * 4)):
            r, g, b, a = pixel

            if col_num > 2 and col_num <= fill_amount and a == 0:
                fill.copy_area(0, 0, 1, 1, img, col_num, row_num)

    icon.set_from_pixbuf(img)


icon = Gtk.StatusIcon()
icon.connect('activate', set_icon_cb)
set_icon(icon)

Gtk.main()

で新しい Pixbuf オブジェクトを作成しようとしましたGdkPixbuf.PixbufLoaderが、これはバイト オブジェクトではなく PNG 画像を想定しているように見えるため、あまり役に立ちません。

fill = GdkPixbuf.PixbufLoader()
fill.write(b'\x88\x88\x88\xff')
fill.close()
fill = fill.get_pixbuf()

# Gives error:
# GLib.Error: gdk-pixbuf-error-quark: Unrecognized image file format (3)

私の次の試みはGdkPixbuf.Pixbuf.new_from_data、有望に見えた を使用することでした:

fill = GdkPixbuf.Pixbuf.new_from_data(b'\xff\x00\xff', GdkPixbuf.Colorspace.RGB,
    False, 8, 1, 1, 3)

ただし、これも機能しません。ピクセルを間違った色に設定するだけでなく、 の複数回の呼び出しで異なる色に設定しますset_icon()print(fill.get_pixels())私に与えますb'\x00\x00\x00'...私はこれを間違って使用していますか? さまざまなパラメーターを関連付けましたが、すべて同じ結果が得られます...

の結果を変更した C の例も見つけましたgdk_pixbuf_get_pixels()。これは、画像データへのポインターを返すためです。しかし、これはPythonでできることではありません(AFAIK)。

私が達成しようとしていることのちょっとした背景:
ラップトップのバッテリーの状態を表示する小さなトレイ アプリケーションがあります。バッテリーアイコンを埋めて、バッテリーの残量を示します。一定の割合を下回ると、色が緑から赤に変わります (これは上記の例で機能します) が、これにはもっと柔軟性が必要です。例えば。他の人が独自の緑の色合いを設定したり、紫を使用したりできるようにします。

4

1 に答える 1

3

それはかなり単純であることが判明しましたが、ドキュメントを読んでもまったく明らかではありません。

# red, green, blue, alpha
color = 0xeeff2dff

# Create blank 1x1 image
fill = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 1, 1)

# Fill entire image with color
fill.fill(color)

私の元の解決策は、アーカイブの目的でここに残されました。これはより複雑であり、透過性では機能しませんが、より高度な操作には適している可能性があります

さらにいじった後GdkPixbuf.PixbufLoader.new_with_type、 を使用することになりました。

list(map(lambda x: x.get_name(), GdkPixbuf.Pixbuf.get_formats()))

「ポータブルエニーマップ形式」またはpnm.

GIMP で単純な 1x1 画像を作成したところ、次のデータが得られました。

>>> open('test.pnm', 'rb').read()
b'P6\n# CREATOR: GIMP PNM Filter Version 1.1\n1 1\n255\n\xff\x00\xff'

最後の 3 バイト ( \xff\x00\xff) は、選択した色です。

私が最終的に使用した完全な例:

color = b'\xee\xff\x2d'

px = GdkPixbuf.PixbufLoader.new_with_type('pnm')
px.write(b'P6\n\n1 1\n255\n' + color)
px.write(color)
px.close()
fill = px.get_pixbuf()

fillその後、元の例のように使用できますfill.copy_area()

ちょっとした回避策ですが、許容範囲です...

PS。
ドキュメントから、GdkPixbuf.Pixbuf.new_from_dataこれを行うための最良のオプションのように見えますが、壊れているようです...何をしても機能しません...

于 2014-11-04T23:22:16.483 に答える