[cairo] Images with stride == width?

Ian Britten britten at caris.com
Tue Jan 20 09:05:13 PST 2009


Chris Wilson wrote:

>> As such, it seems that you cannot make an image surface from an
>> existing block of image data, and will always have to create a
>> new buffer (Using the calculated stride), and copy your source
>> data into the temporary buffer (And then create the image surface
>> using that temporary buffer).
> 
> In general this is true. Note this problem is even more complicated if
> you need to create a surface for h/w acceleration as each piece of h/w
> has it own limitations for valid strides, widths and heights. For the
> image backend, Cairo deliberately only supports a limited number of
> formats in order to avoid the exponential explosion of possible pathways
> and so that the image backend matches the requirements of xlib and we do
> not suffer conversion costs unnecessarily.
> 
> Aside from stride, you also need to be very careful about pixel packing
> and endianess. In particular, if you have an RGB packed-pixel (3 bytes)
> the CAIRO_FORMAT_RGB24 representation is actually xRGB (4 bytes).

Ya, thanks.  Given the plethora of ways of encoding a 'pixel', I don't
blame Cairo for keeping things simple(r).  In the end, *somebody*
usually ends up having to make a copy anyways, due to all the cases
of rowstrides, various pixel formats, premultiplied alphas, etc...

Note that if you ever look to add more support, WX has some clever
'pixel' and 'iterator' classes (done with C++ templates), to help
simplify things and hide how a pixel may be encoded (In case you
haven't seen it before) - Might be a useful technique...
     http://docs.wxwidgets.org/trunk/classwx_pixel_data.html

> Often you find image loaders are far more accommodating when it comes to
> filling buffers (because of the multitude of different formats, as
> above) - see libpng (cairo/src/cairo-png.c) for an example. If you do
> have to convert from a raw image buffer, then I'd recommend using:
>   image = cairo_image_surface_create (CAIRO_FORMAT_XXX, width, height);
>   data = cairo_image_surface_get_data (image);
>   ... copy from buffer to data ...
>   cairo_surface_mark_dirty (image);
> so that the temporary buffer is automatically managed along with the
> image surface referencing it.

get_data()?  Hmmm...  I seem to have missed that - Probably because I
read the documentation.... :P

NOTE - cairomm documentation problem:
http://www.cairographics.org/documentation/cairomm/reference/classCairo_1_1ImageSurface.html#82887e1a0480ab16aa891e135f2b28d6
contains misleading/incorrect comments like this:
"Use this function to create the surface if you don't need access to
  the internal data and want cairo to manage it for you. Since you don't
  have access to the internal data, the resulting surface can only be
  saved to a PNG image file... "
Obviously, you *do* have access to the internal data (via get_data()),
and you can thus save it anywhere you want, not just to a PNG file...

Anyways, thanks for the confirmation/clarification!
Ian


More information about the cairo mailing list