Cairo backend prospects

This is the official definition from the manual:

    > 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.)

    > What I think this means is: cairo ARGB32 is stored not as 4
    > 8-bit quantities, but as one 32-bit int. On big-endian
    > systems the byte order is ARGB, as you would expect, but on
    > little-endian systems (like a PC) the byte order is BGRA.

    > I imagine the reason is that its easier/faster to
    > read/write one 32-bit int than it is to read/write four
    > bytes.

OK, I see the source of my confusion. argb determines the order but
it doesn't determine whether the most significant bit is first or
last....

I added a method buffer_bgra32 to the image backend. I'm not sure
this is the right way to deal with the endianness bit it's easy and
will probably work. I'll leave it to you guys to fix the cairo
backend to selectively call the right method and test it across
platforms, or propose a better solution if you don't like this one...

JDH

Thanks, I used the new buffer_bgra32 and now examples/image_demo.py
looks correct (except that sometimes it looks like the pixels right at
the edge of the image might be corrupted).

The backend_cairo.py code does look a little strange, it calls
  rows, cols, str_ = im.buffer_bgra32()
and then
  X = numx.fromstring (str_, numx.UInt8)
which is used merely to convert the (readonly) string returned from
buffer_bgra32 into a read-write buffer for cairo. If buffer_bgra32
returned a buffer (as its name suggests!) instead of a string this would
not be needed, and it would save copying the image around in memory.

I propose this new version of buffer_bgra32 (and buffer_argb32). I
tested it with cairo and it seems to work OK.

Py::Object
Image::buffer_bgra32(const Py::Tuple& args) {
  //"Return the image object as bgra32";

  _VERBOSE("RendererAgg::buffer_bgra32");

  args.verify_length(0);

  int row_len = colsOut * 4;
  PyObject* py_buffer = PyBuffer_New(row_len * rowsOut);
  if (py_buffer ==NULL)
    throw Py::MemoryError("RendererAgg::buffer_bgra32 could not allocate
memory");
  unsigned char* buf;
  int buffer_len;
  int ret = PyObject_AsWriteBuffer(py_buffer, (void **)&buf,
&buffer_len);
  if (ret !=0)
    throw Py::MemoryError("RendererAgg::buffer_bgra32 could not allocate
memory");

  agg::rendering_buffer rtmp;
  rtmp.attach(buf, colsOut, rowsOut, row_len);

  agg::color_conv(&rtmp, rbufOut, agg::color_conv_rgba32_to_bgra32());
  PyObject* o = Py_BuildValue("llN", rowsOut, colsOut, py_buffer);
  return Py::asObject(o);
}

Steve

Send instant messages to your online friends http://au.messenger.yahoo.com

···

On Thu, 2007-01-11 at 09:56 -0600, John Hunter wrote:

    > This is the official definition from the manual:
    > 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.)

    > What I think this means is: cairo ARGB32 is stored not as 4
    > 8-bit quantities, but as one 32-bit int. On big-endian
    > systems the byte order is ARGB, as you would expect, but on
    > little-endian systems (like a PC) the byte order is BGRA.

    > I imagine the reason is that its easier/faster to
    > read/write one 32-bit int than it is to read/write four
    > bytes.

OK, I see the source of my confusion. argb determines the order but
it doesn't determine whether the most significant bit is first or
last....

I added a method buffer_bgra32 to the image backend. I'm not sure
this is the right way to deal with the endianness bit it's easy and
will probably work. I'll leave it to you guys to fix the cairo
backend to selectively call the right method and test it across
platforms, or propose a better solution if you don't like this one...