2011-03-09 73 views
1

我對開羅圖書館有懷疑。開羅從數據加載圖像

我下載了一張圖片,並將其放入緩衝存儲器中。在開羅有沒有解決方案可以從內存中的數據加載圖像?

感謝

回答

3

您可以從內存中加載圖像數據,但需要按照開羅預期的正確格式佈置該內存。

對於您所描述的內容,將數據保存在tmp文件中並讓Cairo使用FILE操作加載它可能更容易。 Cairo認識到更多格式爲文件類型而不是內存結構。

當我使用cairo_image_surface_create_for_data作爲位圖時,我不得不將我的面向字節的Big-endian位圖數據轉換爲面向32位字的Little-endian行。

你可以從亂扔垃圾的評論中得知,有時我的努力會減少到狩獵和啄食,反覆試驗的方法。但是我用這段代碼得到了期望的輸出。從中竊取你能做的。

一兩件事:爲在內存中的格式(A8,RGB24,ARGB32)文檔在.h EADER文件,而不是參考手冊。

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

該死的!我只注意到我的'anibble [16]'應該有16個值,而不是8個! – 2013-05-03 20:47:55

+0

不能在c中使用超短變量。 i.i.f更多的可讀性會延長nms。 +,條件&循環與morb readbl與{}。 – yeoman 2016-09-08 07:15:06