Каир загрузить изображение из данных - PullRequest
1 голос
/ 09 марта 2011

У меня есть сомнения по поводу библиотеки cairo.

Я загрузил изображение и поместил его в буферную память.Есть ли какое-то решение в Каире, чтобы загрузить изображение из данных, которые есть в памяти?

Спасибо

Ответы [ 3 ]

6 голосов
/ 10 марта 2011

Посмотрите на cairo_image_surface_create_for_data .

3 голосов
/ 14 мая 2012

Вы можете загружать данные изображения из памяти, но вам нужно расположить эту память в правильном формате, который ожидает Каир.

Для того, что вы описываете, вероятно, проще сохранить данные в tmpfile и позволить Cairo загрузить их с помощью операций FILE. Cairo распознает больше форматов как типы файлов, чем как структуры в памяти.

Когда я использовал cairo_image_surface_create_for_data для растровых изображений, мне приходилось преобразовывать мои байтовые данные с прямым порядком байтов в битовые карты в 32-битные слова с прямым порядком байтов.

Вы можете сказать по замороченным комментариям, что иногда мои усилия сводились к методам поиска и проверки, методам проб и ошибок. Но я получил желаемый результат с этим кодом. Укради у него все, что сможешь.

Еще одна вещь: Документация для форматов в памяти (A8, RGB24, ARGB32) находится в файлах .h, а не в справочном руководстве.

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);
    }
}
3 голосов
/ 10 марта 2011

Может быть, вы хотите что-то вроде gdk_pixbuf_new_from_data

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

...