1

我对开罗图书馆有疑问。

我下载了一个图像并将其放入缓冲存储器中。cairo 是否有任何解决方案可以从内存中的数据加载图像?

谢谢

4

3 回答 3

6

看看cairo_image_surface_create_for_data

于 2011-03-10T11:11:24.920 回答
4

您可以从内存中加载图像数据,但您需要以 Cairo 期望的正确格式布置该内存。

根据您的描述,将数据保存在 tmpfile 中并让 Cairo 使用 FILE 操作加载它可能更容易。Cairo 将更多格式识别为文件类型,而不是内存结构。

当我用于cairo_image_surface_create_for_data位图时,我必须将面向字节的 Big-endian 位图数据转换为面向 32 位字的 Little-endian 行。

你可以从乱七八糟的评论中看出,有时我的努力被简化为狩猎和啄食、试错法。但是我用这段代码得到了想要的输出。尽可能从它那里窃取。

还有一件事:内存格式(A8、RGB24、ARGB32)的文档在.header 文件中,而不是参考手册中。

enum { BIG, LITTLE } endian = LITTLE;

inline unsigned char reverse(unsigned char b) {
    return (b&1 ? 0x80: 0)
         | (b&2 ? 0x40: 0)
         | (b&4 ? 0x20: 0)
         | (b&8 ? 0x10: 0)
         | (b&0x10 ? 8: 0)
         | (b&0x20 ? 4: 0)
         | (b&0x40 ? 2: 0)
         | (b&0x80 ? 1: 0);
}

inline unsigned long wreverse(unsigned long w) {
    return ( ( w     &0xFF) << 24)
         | ( ((w>>8) &0xFF) << 16)
         | ( ((w>>16)&0xFF) << 8)
         | ( ((w>>24)&0xFF) );
}



unsigned char abit[2] =  { 0, 0xFF };
unsigned char aspeck[4] = { 0, 0x55, 0xAA, 0xFF };
unsigned char anibble[16] = { 0, 36, 72, 108, 144, 180, 216, 255 };
unsigned char *amap[] = { abit, aspeck, anibble };

void drawimage(state *st, int wid, int hgt, int bits, unsigned char *samp, unsigned char *tmap) {
    int stride;
    //stride = cairo_format_stride_for_width(CAIRO_FORMAT_A8, wid);
    stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, wid);
    //stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, wid);
    int n;
    //unsigned char data[n=stride*hgt];
    unsigned char data[n=stride*hgt*4];
    memset(data, 0, n);
    //unsigned char *data; data = calloc(n=stride*hgt, 1);
    unsigned long *ldata = (void *)data;


    int spo = 8/bits; /* samples per octet */
    int span = wid/spo + (wid%spo?1:0); /* byte width */
    int i,j;
    for (i=0; i < hgt; i++) {
        for (j=0; j < wid; j++) {
            unsigned char t;
            /*if (bits==8) t = samp[i*span + j/spo];
            else*/ t = ( ( samp[i*span + j/spo] >> (/*7 -*/ (j%spo)/* *bits */) )
                     & (0xFF >> (8-bits)) ) /*<< (8-bits)*/;
            if (bits < 8) t = amap[bits==1?0:bits==2?1:2][t];
            t = tmap[t]; /* map value through the transfer map */
            //printf("%2X ", t);
            //data[i*stride + j] = t;
            ldata[i*stride/4 + j] = /*0x80<<24 |*/ t<<16 | t<<8 | t;
        }
        //puts("");
    }
    /*
    for (i=0; i < hgt; i++) {
        //for (j=0; j < stride; j++)
            //printf("%2X ", data[i*stride + j]);
        for (j=0; j < stride/4; j++)
            printf("%2lX ", ldata[i*stride/4 + j] & 0xFF);
        puts("");
    }
    */


    cairo_surface_t *surf;
    //surf = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_A8, wid, hgt, stride);
    surf = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_RGB24, wid, hgt, stride);
    //surf = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, wid, hgt, stride);
    //cairo_mask_surface(st->cr, surf, 0, 0);
    cairo_set_source_surface(st->cr, surf, 0, 0);
    cairo_paint(st->cr);
    cairo_surface_flush(st->surface);
    if (st->dis) XFlush(st->dis);
    cairo_surface_destroy(surf);
    //free(data);
}


OPFN_ void image(state *st, object w, object h, object bits, object mat, object proc) {
    unsigned char tmap[256];
    switch (bits.u.i) {
    case 1: case 2: case 4: case 8: break;
    default: error(st, rangecheck);
    }
    int n;
    int i;
    unsigned char data[n=w.u.i*h.u.i/(8/bits.u.i)];


    /* map gray scale through the transfer function */
    for (i = 0; i < 256; i++) {
        object v;
        v = consreal((double)i/255);
        push(v);
        pushe(consoper(st, "quit", NULL,0,0));
        pushe(consoper(st, "exec", NULL,0,0));
        pushe(consoper(st, "currenttransfer", NULL,0,0));
        run(st);
        v = pop();
        if (v.tag==integertype) promote(v);
        if (v.tag!=realtype) error(st, typecheck);
        tmap[i] = v.u.r * 255;
    }

    for (i = 0; i < n; ) {
        object s;
        pushe(consoper(st, "quit", NULL,0,0));
        pushe(proc);
        run(st);
        if (tos-os < 1) error(st, stackunderflow);
        s = pop();
        if (s.tag != stringtype) error(st, typecheck);
        memcpy(&data[i], STR(s), s.u.c.n);
        i += s.u.c.n;
    }
    if (DEBUG) { for (i=0; i<n; i++) { printf("%02x ", data[i]); } puts(""); }


    if (st->cr) {
        gsave(st);
            cairo_new_path(st->cr);
            cairo_rectangle(st->cr, 0, 0, 1, 1);
            cairo_clip(st->cr);

            {   cairo_matrix_t cm, icm;
                psm2cm(st, mat, &cm);
                cminvert(&cm, &icm);
                cairo_transform(st->cr, &icm);
            }

            cairo_set_source_rgb(st->cr, 0.0, 0.0, 0.0);
            drawimage(st, w.u.i, h.u.i, bits.u.i, data, tmap);
        grestore(st);
    }
}
于 2012-05-14T18:14:49.403 回答
3

也许你想要类似的东西gdk_pixbuf_new_from_data

http://developer.gnome.org/gdk-pixbuf/stable/gdk-pixbuf-Image-Data-in-Memory.html#gdk-pixbuf-new-from-data

于 2011-03-10T09:51:01.970 回答