[cairo] CAIRO_FORMAT_ARGB32 format [ was: Re: "data" in cairo_image_surface_get_data ()
Nguyen Vu Hung
vuhung16plus at gmail.com
Thu Nov 29 19:58:34 PST 2007
2007/11/29, Baz <brian.ewins at gmail.com>:
> > 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;"
>
Thanks. Google really helped:
http://www.eskimo.com/~scs/cclass/notes/sx10b.html
> >
> > 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.
>
Yes, I missed a copy:
data_cairo = (unsigned char *) malloc(w * 4 * h );
> 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.
I am not going to share the buffers between PIX and cairo.
I just want to "convert" PIX->data to cairo's data, create a cairo
surface with that data, then use some cairo APIs with that surface.
>
> >
> > 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.
Where should I use? ( :D, sorry for a dumb question ).
>
> > 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.
>
Yes. My CPU is an Intel Pentium 4.
> 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;
> }
> }
>
Did you missed something?
data_cairo, rowptr are pointers of U8*, but you've casted it to (U32 *)?
rowptr = (U32 *)(data_cairo + i * w * 4);
Or did you mean I have to use
U32* rowptr instead of U8* rowptr?
rowptr[j] = ppixel[j] >> 8; shifts ppixel 8 bits to the right? But
can I make sure that the the last 8 bits ( alpha chanel ) are OK?
When I did so ( declare U32 *rowptr; and loop ), the got an output PNG
file that has all of its pixels are black :).
Is that has something doing with CAIRO_FORMAT_RGB24 in
cairo_image_surface_create_for_data ?
> ... 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.
>
It is somewhat tricky and for me, I found it is hard to understand. I
also want to improve the readability of my code so that the next
maintainer will read it easy.
Here is my code:
U32 wpl = pixGetWpl(pixCut);
U32 w = pixGetWidth(pixCut);
U32 h = pixGetHeight(pixCut);
cairo_surface_t* tmp_surface;
U32* data_cairo;
int stride = wpl * 4;
data_cairo = (unsigned char *) malloc(w * 4 * h );
unsigned char* rowptr;
for (i = 0; i < h; i++) {
ppixel = data + i * wpl;
rowptr = (U8 *) (data_cairo + i * w * 4);
for ( j = 0; j < w; j++) {
rowptr[j] = ppixel[j] >> 8;
}
}
tmp_surface = cairo_image_surface_create_for_data (data_cairo,
CAIRO_FORMAT_RGB24,
w, h,
stride);
--
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