[cairo] Direct manipulation and write to PNG
Andrea Canciani
ranma42 at gmail.com
Mon Jul 9 12:41:42 PDT 2012
On Mon, Jul 9, 2012 at 9:16 PM, Carlos López González
<genetita at gmail.com> wrote:
> Hi!
> I'm working on doing direct manipulation of a image surface data and
> I'm obtaining weird results when writing to png.
>
> I want to obtain a image like this:
> http://imagebin.org/220100
>
> but I get this:
> http://imagebin.org/220098
>
> To create the image I use the following code:
>
> /////////////////////////////////////////////////
> #include <cairo.h>
>
> int main (int argc, char *argv[])
> {
> cairo_surface_t *surface;
> surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 480, 270);
> cairo_surface_flush(surface);
>
> unsigned char* data;
> unsigned char*position;
> int w, h, stride;
> data=cairo_image_surface_get_data(surface);
> w=cairo_image_surface_get_width(surface);
> h=cairo_image_surface_get_height(surface);
> stride=cairo_image_surface_get_stride(surface);
> unsigned char a, r, g, b;
> int x, y;
> a=255;
> r=178;
> g=55;
> b=55;
> for(y=0; y<h; y++)
> {
> for(x=0; x<w*4; x+=4)
> {
> position= (unsigned char*)(((char*)data)+y*stride);
> position[x]=a;
> position[x+1]=r;
> position[x+2]=g;
> position[x+3]=b;
This is wrong as it won't work on little-endian machines.
You should access pixels as uint32_t pointers:
uint32_t *okposition=
(uint32_t*)(((char*)data)+y*stride);
okposition[x/4]=(a << 24) | (r << 16) | (g << 8) | b;
> }
> }
> cairo_surface_mark_dirty(surface);
>
> cairo_surface_write_to_png(surface, "image.png");
>
> cairo_surface_destroy(surface);
>
> return 0;
> }
> //////////////////////////////////////////////
>
> I compiled it with:
>
> $ gcc -o cairo4 `pkg-config --cflags --libs gtk+-2.0` cairo4.c
>
> The png image file has the color somehow twisted and modified:
> a=56
> r=255
> g=9
> b=88
>
> I've re-checked that the written bytes are fine on the memory but I
> don't get the right results on the png file.
> Can anyone help me to let me know what I'm doing wrong? Or maybe it is
> something related to png backend?
The issue was simply that you were assuming a different byte order
than the one used on your machine.
To avoid having these issues, always access whole pixels.
Some documentation about pixel formats can be found here:
http://cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t
As you can see, ARGB32 is a 32-bits format stored native-endian.
I hope this helps, but don't hesitate to ask for more clarification if
it is not sufficient.
Andrea
>
> Thank you very much!!
> --
> Carlos
> http://synfig.org
> --
> cairo mailing list
> cairo at cairographics.org
> http://lists.cairographics.org/mailman/listinfo/cairo
More information about the cairo
mailing list