Cairo load image from data

故事扮演 提交于 2019-12-11 07:00:42

问题


I have a doubt with cairo library.

I downloaded an image and I put it into a buffer memory. Is there any solution in cairo to load an image from data that there is in memory?

Thanks


回答1:


Maybe you want something like gdk_pixbuf_new_from_data

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




回答2:


Give a look to cairo_image_surface_create_for_data.




回答3:


You can load image data from memory, but you need to lay out that memory in the correct format that Cairo expects.

For what you describe, it's probably easier to save the data in a tmpfile and let Cairo load it using FILE operations. Cairo recognizes more formats as filetypes than it does as in-memory structures.

When I used cairo_image_surface_create_for_data for bitmaps, I had to convert my byte-oriented Big-endian bitmap data into 32bit-word-oriented Little-endian rows.

You can tell from the littering of comments, that at times my efforts were reduced to hunt-and-peck, trial-and-error methods. But I got the desired output with this code. Steal from it what you can.

One more thing: The documentation for the in-memory formats (A8, RGB24, ARGB32) is in the .header files, not the reference manual.

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);
    }
}


来源:https://stackoverflow.com/questions/5249644/cairo-load-image-from-data

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!