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);
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.