更改GdkPixbuf(GTK3)中像素的颜色

2024-04-25 05:55:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用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()

我尝试用GdkPixbuf.PixbufLoader创建一个新的Pixbuf对象,但这似乎需要一个PNG图像,而不是一个bytes对象,因此这不是很有帮助:

^{pr2}$

我的下一个尝试是使用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中你做不到。在

关于我要完成的事情的一些背景知识:
我有一个小托盘应用程序来显示我的笔记本电脑的电池状态;它会填满电池图标以指示电池剩余电量。低于一定的百分比,颜色从绿色变为红色(这与上面的例子一样有效),但我希望在这方面有更多的灵活性;例如允许其他人设置自己的绿色阴影,或使用紫色,或其他任何东西。在


Tags: fromgtkimgnewdataget颜色像素
1条回答
网友
1楼 · 发布于 2024-04-25 05:55:46

事实证明这很简单,但从阅读文档来看一点也不明显:

^{1}$

我原来的解决方案,留在这里是为了存档;这是一个更复杂的解决方案,不具备透明性,但它可能更适合更高级的操作

经过更多的捣乱,我最终使用了GdkPixbuf.PixbufLoader.new_with_type,来自:

^{pr2}$

我选择最简单的图像格式,它看起来是“可移植的anymap格式”或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()

这是一个解决办法,但可以接受。。。在

注:
从文档中看,GdkPixbuf.Pixbuf.new_from_data看起来是最好的选择,但是它似乎已经失败了。。。不管我做什么我都不能工作。。。在

相关问题 更多 >