[cairo] CAIRO_FORMAT_ARGB32 format [ was: Re: "data" in cairo_image_surface_get_data ()

Baz brian.ewins at gmail.com
Thu Nov 29 05:17:19 PST 2007


On Nov 29, 2007 11:57 AM, Nguyen Vu Hung <vuhung16plus at gmail.com> wrote:
> 2007/11/28, Baz <brian.ewins at gmail.com>:
>
> > So, assuming you are using a buffer which has padding around it as
> > above (ie you've allocated it yourself and used
> > cairo_image_surface_create_for_data), setting up a PIX structure for
> > an RGB24 buffer is something like
> >
> > pix.w = cairo_image_surface_get_width (surf);
> > pix.h = cairo_image_surface_get_height (surf);
> > pix.d = 8;
> > pix.wpl = cairo_image_surface_get_stride (surf) / 4;
> > pix.data = cairo_image_surface_get_data (surf) + 1; // big-endian;
> > little endian would have -1 here.
> >
> I don't understand your code.
> pix.data, cairo_image_surface_get_data (surf) are pointers, is
>
> pix.data = cairo_image_surface_get_data (surf) + 1;
>
> syntax valid?

When I say 'roughly' I mean I'm not posting tested code, I'm just
outlining the steps. But yes you can do stuff like that.

http://www.google.com/search?q=pointer+arithmetic

BTW you use pointer arithmetic in your own code: "ppixel = data + i * wpl;"

>
> I'ved tried to convert back PIX to cairo's data format. In the
> following code, I get PIX's data byte by byte, and set it to cairo's
> data pointer. The code runs fine, but when I write cairo's *data to a
> PNG file, the PNG output is weird.
>
> One more point, In the function
>
> cairo_image_surface_create_for_data
>
> do I have to set the last paramater ( stride ) to wpl * 4 or w * 4?

Answered below.

>
>     U32    *data, *ppixel;
>
>     data = (U32*) pixGetData(pixCut); // PIX->data format
>
>     U32 wpl = pixGetWpl(pixCut); // word per line
>     U32 w = pixGetWidth(pixCut); // pix width
>     U32 h = pixGetHeight(pixCut); // pix height
>
>     cairo_surface_t* tmp_surface;
>     unsigned char * data_cairo;

You've missed out a line that allocates this buffer? Its hard to tell
what you intended the stride to be without that.

BTW the point of using create_for_data was that to do the
buffer-sharing trick you need to have allocated memory which extends
beyond that needed for either PIX or RGB24, and that destroying the
image surface should not free the buffer since its not owned by the
image surface. If you're not going to try to share the buffer, you can
just use cairo_image_surface_create, it's simpler.

>
>     int  i, j, k;
>
>     unsigned char* rowptr;
>
>     for (i = 0; i < h; i++) {
>       ppixel = data + i * wpl;
>       rowptr = &data_cairo[i * w * 4];

(w * 4) here should be whatever cairo_image_surface_get_stride()
returns. If you used cairo_image_surface_create before the loop, you
would call cairo_image_surface_get_stride() to find this out, if you
used cairo_image_surface_create_for_data passing in (wpl * 4) as
stride as you do below, you know the value is going to be (wpl * 4).
In either case you might as well declare

int stride = wpl * 4; and use it in both places.

>       for ( j = k = 0; j < w ; j++) {
>         rowptr[k++] = GET_DATA_BYTE(ppixel, COLOR_BLUE);
>         rowptr[k++] = GET_DATA_BYTE(ppixel, COLOR_GREEN);
>         rowptr[k++] = GET_DATA_BYTE(ppixel, COLOR_RED);
>         rowptr[k++] = 0xff; // alpha,
>         ppixel++;

I assume you're only running this on a little-endian platform? You're
writing the data byte-by-byte, instead of word-by-word. See the
previous post.

Just to spell things out - this is what the previous post implied:
     for (i = 0; i < h; i++) {
       ppixel = data + i * wpl;
       rowptr = (U32 *)(data_cairo + i * w * 4);
       for ( j = 0; j < w ; j++) {
           rowptr[j] = ppixel[j] >> 8;
       }
    }

... if you go back and reread what I said in the previous mail you
should see that this loop can be replaced with two memcpy()s, one for
the big-endian case and one for the little-endian case.

>       }
>     }
>
> http://cairographics.org/manual/cairo-Image-Surfaces.html#cairo-image-surface-create-for-data
>     tmp_surface = cairo_image_surface_create_for_data (data_cairo,
>                                //CAIRO_FORMAT_ARGB32,
>                                CAIRO_FORMAT_RGB24,
>                                w, h,
>                                wpl * 4);
>
>
> http://aoclife.ddo.jp/~vuhung/tmp/leptonlib-1.51/src/arrayaccess.h
> #define  GET_DATA_BYTE(pdata, n)              l_getDataByte(pdata, n)
>
> http://aoclife.ddo.jp/~vuhung/tmp/leptonlib-1.51/src/arrayaccess.c
> /*!
>  *  l_getDataByte()
>  *
>  *      Input:  line  (ptr to beginning of data line)
>  *              n     (pixel index)
>  *      Return: value of the n-th (byte) pixel
>  */
> l_int32
> l_getDataByte(l_uint32  *line,
>               l_int32    n)
> {
> #ifdef  L_BIG_ENDIAN
>     return *((l_uint8 *)line + n);
> #else  /* L_LITTLE_ENDIAN */
>     return *(l_uint8 *)((l_uintptr_t)((l_uint8 *)line + n) ^ 3);
> #endif  /* L_BIG_ENDIAN */
> }
>
> http://aoclife.ddo.jp/~vuhung/tmp/leptonlib-1.51/src/pix.h
> /*-------------------------------------------------------------------------*
>  *                             Colors for 32 bpp                           *
>  *-------------------------------------------------------------------------*/
> /* Note: colors are used in 32 bpp images.  The 4th byte, typically
>  *       known as the "alpha channel", can be used for blending.
>  *       It's not explicitly used in leptonica.  */
> enum {
>     COLOR_RED = 0,
>     COLOR_GREEN = 1,
>     COLOR_BLUE = 2,
>     L_ALPHA_CHANNEL = 3
> };
>
>
> --
>
> Best Regards,
> Nguyen Hung Vu
> vuhung16plus{remove}@gmail.dot.com
> An inquisitive look at Harajuku
> http://www.flickr.com/photos/vuhung/sets/72157600109218238/
>


More information about the cairo mailing list