Convert PIL image to Cairo ImageSurface

I am trying to create a Cairo ImageSurface from a PIL image, the code that I still have:

im = Image.open(filename)
imstr = im.tostring()
a = array.array('B', imstr)
height, width = im.size
stride = cairo.ImageSurface.format_stride_for_width(cairo.FORMAT_RGB24, width)
return cairo.ImageSurface.create_for_data(a, cairo.FORMAT_ARGB24, width, height, stride)

But it gives me

TypeError: buffer is not long enough.

I really don’t understand why this is so, maybe I don’t understand the image formats enough.

I am using cairo 1.10.

+5
source share
2 answers

Cairo create_for_data () wants a writable buffer object (a string can be used as a buffer object, but it is not written), and it only supports 32-bit data per channel (RGBA or RGB, followed by one unused byte), On the other hand, PIL provides a 24-bit read-only RGB buffer object.

PIL, -, PIL numpy, Cairo.

im = Image.open(filename)
im.putalpha(256) # create alpha channel
arr = numpy.array(im)
height, width, channels = arr.shape
surface = cairo.ImageSurface.create_for_data(arr, cairo.FORMAT_RGB24, width, height)
+3

, :

  • , RGB (A)

, 32- , . , PIL:

r1 g1 b1 a1 r2 g2 b2 a2 ...

cairo :

b1*a1 g1*a1 r1*a1 a1 b2*a2 g2*a2 r2*a2 a2 ...

:

a1 r1*a1 b1*a1 g1*a1 a2 r2*a2 g2*a2 b2*a2 ...

, NumPy:

def pil2cairo(im):
    """Transform a PIL Image into a Cairo ImageSurface."""

    assert sys.byteorder == 'little', 'We don\'t support big endian'
    if im.mode != 'RGBA':
        im = im.convert('RGBA')

    s = im.tostring('raw', 'BGRA')
    a = array.array('B', s)
    dest = cairo.ImageSurface(cairo.FORMAT_ARGB32, im.size[0], im.size[1])
    ctx = cairo.Context(dest)
    non_premult_src_wo_alpha = cairo.ImageSurface.create_for_data(
        a, cairo.FORMAT_RGB24, im.size[0], im.size[1])
    non_premult_src_alpha = cairo.ImageSurface.create_for_data(
        a, cairo.FORMAT_ARGB32, im.size[0], im.size[1])
    ctx.set_source_surface(non_premult_src_wo_alpha)
    ctx.mask_surface(non_premult_src_alpha)
    return dest

. NumPy, . (Mac OS X, 2.13 Intel Core 2 Duo) ~ 1s 6000x6000 5 500 × 500 .

+3

All Articles