Python 如何使用Cairo将图像转换为灰度
我想把一个图像,可能是一个alpha通道,转换成cairo 我编写的代码将完全不透明的图像转换为灰度,但在图像包含alpha通道时失败:Python 如何使用Cairo将图像转换为灰度,python,cairo,Python,Cairo,我想把一个图像,可能是一个alpha通道,转换成cairo 我编写的代码将完全不透明的图像转换为灰度,但在图像包含alpha通道时失败: import cairo CAIRO_OPERATOR_HSL_LUMINOSITY = 28 # my py2cairo seems outdated def convert_to_grayscale(img_in): img_out = img_in.create_similar( cairo.CONTENT_COLOR_ALP
import cairo
CAIRO_OPERATOR_HSL_LUMINOSITY = 28 # my py2cairo seems outdated
def convert_to_grayscale(img_in):
img_out = img_in.create_similar(
cairo.CONTENT_COLOR_ALPHA, img_in.get_width(), img_in.get_height())
cr = cairo.Context(img_out)
cr.set_source_rgba(1, 1, 1, 1)
cr.paint()
cr.set_source_surface(img_in)
cr.set_operator(CAIRO_OPERATOR_HSL_LUMINOSITY)
cr.paint()
return img_out
包含RGBA值(20、30、40、255)的图像将(正确)转换为(28、28、28、255)。但是,如果图像不是完全不透明的,则结果将是错误的,例如,如果我使用颜色(10、15、20、128)转换图像,我将在预期(14、14、14、128)[*]时返回(141、141、141、25)。我怎样才能得到一个能很好地处理半透明图像的convert_to_grayscale版本
[*]请注意,这些值的RGB值与它们的alpha值相乘,这在开罗很常见。我终于成功地使用NumPy转换了关于原始alpha的图像。我在开罗邮件列表中询问过,但我得到的唯一替代方案与我的版本有相同的问题(即,它不尊重最初的alpha通道) 以下是我的解决方案:
import cairo
import numpy
import sys
def convert_to_grayscale(img_in):
"""Convert an image to grayscale.
Arguments:
img_in: (cairo.ImageSurface) input image.
Return:
(cairo.ImageSurface) image in grayscale, in ARGB32 mode.
Timing:
~100ms to convert an image of 800x800
Examples:
# returns a B&W image
>>> convert_to_grayscale(cairo.ImageSurface.create_from_png('test.png'))
"""
a = numpy.frombuffer(img_in.get_data(), numpy.uint8)
w, h = img_in.get_width(), img_in.get_height()
a.shape = (w, h, 4)
assert sys.byteorder == 'little', (
'The luminosity vector needs to be switched if we\'re in a big endian architecture. '
'The alpha channel will be at position 0 instead of 3.')
alpha = a[:, :, 3]
alpha.shape = (w, h, 1)
luminosity_float = numpy.sum(a * numpy.array([.114, .587, .299, 0]), axis=2)
luminosity_int = numpy.array(luminosity_float, dtype=numpy.uint8)
luminosity_int.shape = (w, h, 1)
grayscale_gbra = numpy.concatenate((luminosity_int, luminosity_int, luminosity_int, alpha),
axis=2)
stride = cairo.ImageSurface.format_stride_for_width(cairo.FORMAT_ARGB32, w)
assert stride == 4 * w, 'We need to modify the numpy code if the stride is different'
img_out = cairo.ImageSurface.create_for_data(grayscale_gbra, cairo.FORMAT_ARGB32, w, h, stride)
return img_out
我今天也试着做同样的事情,并且想出了一个不同的方法。实际上我并没有用Python来做这件事,事实上我根本不懂Python,所以我不能提供任何代码。但是,以下是我所做的:
- 从原始图像创建曲面
- 为该曲面创建图案
- 使用图案作为遮罩,应用带有CAIRO_运算符_HSL_饱和度的rgb源(黑色)
s
是新的cairo\u曲面,而cr
是其关联的cairo\u t;假设您已经将原始图片放在那里):
在这里添加它,以防/希望它可能对某些人有所帮助。这并不能回答问题。这对我很有用。代码翻译成Cairocffi API的过程非常简单,并且工作正常。
a.shape=(h,h,4)
a(w,h,4)
的打字错误?
cairo_pattern_t *pattern = cairo_pattern_create_for_surface (s);
cairo_rectangle (cr, 0, 0, width, height);
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_set_operator (cr, CAIRO_OPERATOR_HSL_SATURATION);
cairo_mask (cr, pattern);
cairo_pattern_destroy (pattern);