Dealing with 1bpp bitmaps in cairo
Mark Leisher <[email protected]>
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[email protected]> |
In updating http://www.math.nmsu.edu/~mleisher/Software/gbdfed to use GTK+ 3 and cairo, I needed to render a moderate number (128 to 256) of discrete 1bpp images. After lots of experimentation, I finally settled on the code below. Please note that this code has not been tested for endian issues yet, so some tweaking may be necessary. FYI: once you have the surface, you can call cairo_mask_surface() to actually render the bitmap. Took me a while to figure that one out. If there is any better way to deal with this, please let me know. -- Mark Leisher -- cairo mailing list [email protected] http://lists.cairographics.org/mailman/listinfo/cairo
cbm.c
(text/x-csrc, 1.6 KB)
/*
* For memset().
*/
#include <string.h>
/*
* For cairo and GLib.
*/
#include <gdk/gdk.h>
typedef struct {
guint32 *img;
guint size;
guint stride;
} cbm_t;
static guint32
reverse_bits(guint32 v)
{
guint32 i, o;
for (i = 32, o = 0; i; i--) {
o <<= 1;
o |= (v & 1);
v >>= 1;
}
return o;
}
cairo_surface_t *
cairo_image_surface_for_bitmap(guchar *bmap, guint16 wd, guint16 ht, cbm_t *im)
{
guint need, x, y, i, bpr, qstride;
guint32 *rp;
im->stride = cairo_format_stride_for_width(CAIRO_FORMAT_A1,wd);
qstride = im->stride >> 2;
/*
* Figure out how much space will be needed.
*/
need = qstride * ht;
if (need > im->size) {
if (im->size == 0)
im->img = (guint32 *) g_malloc(sizeof(guint32) * need);
else
im->img = (guint32 *) g_realloc(im->img, sizeof(guint32) * need);
im->size = need;
}
memset(im->img,0,sizeof(guint32)*im->size);
bpr = (wd>>3)+((wd&7)?1:0);
/*
* Transfer the bitmap into the image.
*/
for (rp = im->img, y = 0; y < ht; y++, rp += qstride) {
for (x = i = 0; x < bpr; x++) {
if (x && !(x & 3)) {
rp[i] = reverse_bits(rp[i]);
i++;
}
rp[i] |= bmap[(y*bpr)+x] << ((3-(x & 3))<<3);
}
rp[i] = reverse_bits(rp[i]);
}
/*
* Create the surface.
*/
return cairo_image_surface_create_for_data((unsigned char *) im->img,
CAIRO_FORMAT_A1,
wd, ht, im->stride);
}