[cairo] how to import .BMP without other libs(GTK+ etc)?

Thomas Stover thomas at wsinnovations.com
Wed Feb 4 21:30:31 PST 2009

Aliner wrote:
> How did you handle the alpha channel in (for example) gif images?

ok let me see here... It's been about a year since I did this. If we get
it working, we need to make some notes or something...
>     ExceptionInfo *exception;
>     Image    *image;
>     ImageInfo *image_info;

>     long x, y;
>     const PixelPacket *p;
>     QuantizeInfo *qinfo;
I haven't used a QuantizeInfo before. Are you working with a palletized
file or are you trying to dither down? come to think of it, I don't know
that ever used cairo with less than 24bit... moving on....

>     unsigned char *q;
>     unsigned char *imgbuf;
>     /*
>      * Initialize the image info structure and read an image.
>      */
>     MagickCoreGenesis(*argv,MagickTrue);
>     exception  = AcquireExceptionInfo();
>     image_info = CloneImageInfo((ImageInfo *) NULL);
>     (void) strcpy(image_info->filename,argv[1]);
>     image = ReadImage(image_info,exception);
>     if (exception->severity != UndefinedException)
>         CatchException(exception);
>     if (image == (Image *) NULL)
>         exit(1);

I was using the BlobToImage() function, because I was getting the files
from databases and network sources. That looks right to me though...
>     printf("rows = %ld, columns= %ld\n", image->rows, image->columns);
>    imgbuf = (unsigned char 
> *)malloc(image->rows*image->columns*sizeof(char)*4);
>     q = imgbuf;
>     for(y=0; y < (long) image->rows; y++)
>     {
>         p = GetVirtualPixels(image, 0, y, image->columns, 1, exception);
>         if( p == (const PixelPacket *)NULL )
>             break;
I was using AcquireImagePixels() which also returns a PixelPacket *, but
I'd have to go back and see what the difference is. yours may be better..

>         for( x = 0; x < (long) image->columns; x++)
>         {
>             *q = ScaleQuantumToChar(p->blue);
>             q++;
I wonder if the ImageMagick API has changed since I last did this. I had
to go look at the docs some. Apparently the PixelPacket members blue,
green, red, and opacity, are or at least can be 16bit integers. My old
code has them just as single bytes. That explains what your ScaleQuantum
stuff is doing. I get it now. I can't find that function in their docs
though. (their documentation is kind of all over the place, isn't it?)
Maybe that's part of the difference between GetVirtualPixels() and
AcquireImagePixels()? Anyway....

>             *q = ScaleQuantumToChar(p->green);
>             q++;
>             *q = ScaleQuantumToChar(p->red);
>             q++;
>             *q = ScaleQuantumToChar(p->opacity);
>             q++;
>             p++;
>         }
>     }
Looks like you're almost there. One of the tricks is that cairo is using
"alpha" or "how transparent is something", they use "opacity" which is
the opposite! So use some subtraction. I had the one byte values so I
was doing alpha = 255 - opacity; with these 16bit values you have
enlightened me to, I would use alpha = 65535 - opacity. That needs some
more exploring.

> Is this the right way?
> Juan Aranda
Beyond that to turn that into a cairo surface, I will point to my old
experiment code...

cairo_surface_t *surface;
Image *image;
PixelPacket *pixels;
int x, y, length;

pixels =
AcquireImagePixels(image, 0, 0, image->magick_columns,
                    image->magick_rows, &exception);

for(y = 0; y < image->magick_rows; y++)
  for(x = 0; x < image->magick_columns; x++)
   pixels[(y * image->magick_columns) + x].opacity = 255;

surface =
cairo_image_surface_create_for_data((unsigned char *) image,



For your code you presumably could 'q' for 'image', but its in BGRA and
this is in ARGB. If cairo doesn't do that format, just rearrange.

Let me know how that works out. I might try it again myself and make
some real examples to put on my website or something. That unsigned char
vs short int thing sure is an issue.


More information about the cairo mailing list