gpt4 book ai didi

python - 将 ARGB32 (py)cairo 表面转换为 PIL(low) 图像 - 反色?

转载 作者:行者123 更新时间:2023-12-04 12:33:45 24 4
gpt4 key购买 nike

我想我正在做一些微不足道的标准任务:我正在转换一个 (py) cairo表面到 PIL (低)图像。原版cairo表面用途ARGB模式。目标PIL图片使用 RGBA ,即我想保留所有颜色和 alpha channel 。然而,转换中的事情变得非常奇怪:似乎 cairo在内部将其数据存储为 BGRA ,所以我实际上需要在转换过程中交换颜色 channel ,请参见此处:

import cairo

import gi
gi.require_version('Rsvg', '2.0')
from gi.repository import Rsvg

from PIL import Image

w, h = 600, 600
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h,)
ctx = cairo.Context(surface)

ctx.set_source_rgba(1.0, 1.0, 1.0, 1.0) # explicitly draw white background
ctx.rectangle(0, 0, w, h)
ctx.fill()

# tested with https://raw.githubusercontent.com/pleiszenburg/abgleich/v0.0.7/src/abgleich/share/icon.svg
layout = Rsvg.Handle.new_from_file('icon.svg')
layout.render_cairo(ctx)

# EXPORT TEST #1: cairo
surface.write_to_png('export_cairo.png') # ok, looks as expected

pil = Image.frombuffer(mode = 'RGBA', size = (w, h), data = surface.get_data(),)

b, g, r, a = pil.split() # Color swap, part 1: Splitting the channels
pil = Image.merge('RGBA', (r, g, b, a)) # Color swap, part 2: Rearranging the channels

# EXPORT TEST #2: PIL
pil.save('export_pil.png') # ok, looks as expected IF COLORS ARE REARRANGED AS ABOVE
以上测试使用 rsvg ,但也可以简单地用 cairo画几条彩色线条来重现。 .
我是不是真的误解了什么,或者这实际上是正确的方法吗?

最佳答案

从开罗文档( https://www.cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t ):

CAIRO_FORMAT_ARGB32

each pixel is a 32-bit quantity, with alpha in the upper 8 bits, then red, then green, then blue. The 32-bit quantities are stored native-endian. Pre-multiplied alpha is used. (That is, 50% transparent red is 0x80800000, not 0x80ff0000.) (Since 1.0)


所以,在小端,我认为这实际上就是 PIL 所说的 BGRA。
与您的问题没有直接关系,但这是预乘 alpha。
根据 https://pillow.readthedocs.io/en/stable/handbook/concepts.html#concept-modes ,具有预乘 alpha 的唯一模式是 'RGBa' .

or is this actually the right way to do it?


不知道“正确”是什么意思。但是,我的评论是:必须有某种方法可以在不通过中间图像的情况下做到这一点。
由于 Pillow 不支持 cairo 的图像模式,也许您可​​以使用 numpy-y 来进行转换。例如,pycairo 的测试套件包含以下内容: https://github.com/dalembertian/pycairo/blob/22d29e0820d0dcbe070a6eb6f8f302e8c41b71a7/test/isurface_get_data.py#L37-L42
buf = surface.get_data()
a = numpy.ndarray (shape=(w,h,4), dtype=numpy.uint8, buffer=buf)

# draw a vertical line
a[:,40,0] = 255 # byte 0 is blue on little-endian systems
a[:,40,1] = 0
a[:,40,2] = 0
因此,要从(用枕头说)BGRa 转换为 RGBa,您可以执行以下操作来交换红色和蓝色 channel (其中 a 是与上述类似的缓冲区):
(a[:,:,0], a[:,:,2]) = (a[:,:,2], a[:,:,0])
如果这真的比您通过中级的方法更好 Image ……好吧,我不知道。您必须判断执行此操作的最佳方法是什么。至少你现在应该能够解释为什么它是必要的(cairo 和 PIL 都没有支持通用的图像格式)

关于python - 将 ARGB32 (py)cairo 表面转换为 PIL(low) 图像 - 反色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63482663/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com