Home | History | Annotate | Download | only in qemu
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 #include <png.h>
      5 
      6 #if 0
      7 #define LOG(x...) fprintf(stderr,"error: " x)
      8 #else
      9 #define LOG(x...) do {} while (0)
     10 #endif
     11 
     12 void *loadpng(const char *fn, unsigned *_width, unsigned *_height)
     13 {
     14     FILE *fp = 0;
     15     unsigned char header[8];
     16     unsigned char *data = 0;
     17     unsigned char **rowptrs = 0;
     18     png_structp p = 0;
     19     png_infop pi = 0;
     20 
     21     png_uint_32 width, height;
     22     int bitdepth, colortype, imethod, cmethod, fmethod, i;
     23 
     24     p = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
     25     if(p == 0) {
     26         LOG("%s: failed to allocate png read struct\n", fn);
     27         return 0;
     28     }
     29 
     30     pi = png_create_info_struct(p);
     31     if(pi == 0) {
     32         LOG("%s: failed to allocate png info struct\n", fn);
     33         goto oops;
     34     }
     35 
     36     fp = fopen(fn, "rb");
     37     if(fp == 0) {
     38         LOG("%s: failed to open file\n", fn);
     39         return 0;
     40     }
     41 
     42     if(fread(header, 8, 1, fp) != 1) {
     43         LOG("%s: failed to read header\n", fn);
     44         goto oops;
     45     }
     46 
     47     if(png_sig_cmp(header, 0, 8)) {
     48         LOG("%s: header is not a PNG header\n", fn);
     49         goto oops;
     50     }
     51 
     52     if(setjmp(png_jmpbuf(p))) {
     53         LOG("%s: png library error\n", fn);
     54     oops:
     55         png_destroy_read_struct(&p, &pi, 0);
     56         if(fp != 0) fclose(fp);
     57         if(data != 0) free(data);
     58         if(rowptrs != 0) free(rowptrs);
     59         return 0;
     60     }
     61 
     62     png_init_io(p, fp);
     63     png_set_sig_bytes(p, 8);
     64 
     65     png_read_info(p, pi);
     66 
     67     png_get_IHDR(p, pi, &width, &height, &bitdepth, &colortype,
     68                  &imethod, &cmethod, &fmethod);
     69 //    printf("PNG: %d x %d (d=%d, c=%d)\n",
     70 //           width, height, bitdepth, colortype);
     71 
     72     switch(colortype){
     73     case PNG_COLOR_TYPE_PALETTE:
     74         png_set_palette_to_rgb(p);
     75         break;
     76 
     77     case PNG_COLOR_TYPE_RGB:
     78         if(png_get_valid(p, pi, PNG_INFO_tRNS)) {
     79             png_set_tRNS_to_alpha(p);
     80         } else {
     81             png_set_filler(p, 0xff, PNG_FILLER_AFTER);
     82         }
     83         break;
     84 
     85     case PNG_COLOR_TYPE_RGB_ALPHA:
     86         break;
     87 
     88     case PNG_COLOR_TYPE_GRAY:
     89         if(bitdepth < 8) {
     90             png_set_gray_1_2_4_to_8(p);
     91         }
     92 
     93     default:
     94         LOG("%s: unsupported (grayscale?) color type\n");
     95         goto oops;
     96     }
     97 
     98     if(bitdepth == 16) {
     99         png_set_strip_16(p);
    100     }
    101 
    102     data = (unsigned char*) malloc((width * 4) * height);
    103     rowptrs = (unsigned char **) malloc(sizeof(unsigned char*) * height);
    104 
    105     if((data == 0) || (rowptrs == 0)){
    106         LOG("could not allocate data buffer\n");
    107         goto oops;
    108     }
    109 
    110     for(i = 0; i < height; i++) {
    111         rowptrs[i] = data + ((width * 4) * i);
    112     }
    113 
    114     png_read_image(p, rowptrs);
    115 
    116     png_destroy_read_struct(&p, &pi, 0);
    117     fclose(fp);
    118     if(rowptrs != 0) free(rowptrs);
    119 
    120     *_width = width;
    121     *_height = height;
    122 
    123     return (void*) data;
    124 }
    125 
    126 
    127 typedef struct
    128 {
    129     const unsigned char*  base;
    130     const unsigned char*  end;
    131     const unsigned char*  cursor;
    132 
    133 } PngReader;
    134 
    135 static void
    136 png_reader_read_data( png_structp  png_ptr,
    137                       png_bytep   data,
    138                       png_size_t  length )
    139 {
    140   PngReader* reader = png_get_io_ptr(png_ptr);
    141   png_size_t avail  = (png_size_t)(reader->end - reader->cursor);
    142 
    143   if (avail > length)
    144       avail = length;
    145 
    146   memcpy( data, reader->cursor, avail );
    147   reader->cursor += avail;
    148 }
    149 
    150 
    151 void *readpng(const unsigned char *base, size_t   size, unsigned *_width, unsigned *_height)
    152 {
    153     PngReader  reader;
    154     unsigned char *data = 0;
    155     unsigned char **rowptrs = 0;
    156     png_structp p = 0;
    157     png_infop pi = 0;
    158 
    159     png_uint_32 width, height;
    160     int bitdepth, colortype, imethod, cmethod, fmethod, i;
    161 
    162     p = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    163     if(p == 0) {
    164         LOG("%s: failed to allocate png read struct\n", fn);
    165         return 0;
    166     }
    167 
    168     pi = png_create_info_struct(p);
    169     if(pi == 0) {
    170         LOG("%s: failed to allocate png info struct\n", fn);
    171         goto oops;
    172     }
    173 
    174     reader.base   = base;
    175     reader.end    = base + size;
    176     reader.cursor = base;
    177 
    178     if(size < 8 || png_sig_cmp((unsigned char*)base, 0, 8)) {
    179         LOG("%s: header is not a PNG header\n", fn);
    180         goto oops;
    181     }
    182 
    183     reader.cursor += 8;
    184 
    185     if(setjmp(png_jmpbuf(p))) {
    186         LOG("%s: png library error\n", fn);
    187     oops:
    188         png_destroy_read_struct(&p, &pi, 0);
    189         if(data != 0) free(data);
    190         if(rowptrs != 0) free(rowptrs);
    191         return 0;
    192     }
    193 
    194     png_set_read_fn (p, &reader, png_reader_read_data);
    195     png_set_sig_bytes(p, 8);
    196 
    197     png_read_info(p, pi);
    198 
    199     png_get_IHDR(p, pi, &width, &height, &bitdepth, &colortype,
    200                  &imethod, &cmethod, &fmethod);
    201 //    printf("PNG: %d x %d (d=%d, c=%d)\n",
    202 //           width, height, bitdepth, colortype);
    203 
    204     switch(colortype){
    205     case PNG_COLOR_TYPE_PALETTE:
    206         png_set_palette_to_rgb(p);
    207         break;
    208 
    209     case PNG_COLOR_TYPE_RGB:
    210         if(png_get_valid(p, pi, PNG_INFO_tRNS)) {
    211             png_set_tRNS_to_alpha(p);
    212         } else {
    213             png_set_filler(p, 0xff, PNG_FILLER_AFTER);
    214         }
    215         break;
    216 
    217     case PNG_COLOR_TYPE_RGB_ALPHA:
    218         break;
    219 
    220     case PNG_COLOR_TYPE_GRAY:
    221         if(bitdepth < 8) {
    222             png_set_gray_1_2_4_to_8(p);
    223         }
    224 
    225     default:
    226         LOG("%s: unsupported (grayscale?) color type\n");
    227         goto oops;
    228     }
    229 
    230     if(bitdepth == 16) {
    231         png_set_strip_16(p);
    232     }
    233 
    234     data    = (unsigned char*) malloc((width * 4) * height);
    235     rowptrs = (unsigned char **) malloc(sizeof(unsigned char*) * height);
    236 
    237     if((data == 0) || (rowptrs == 0)){
    238         LOG("could not allocate data buffer\n");
    239         goto oops;
    240     }
    241 
    242     for(i = 0; i < height; i++) {
    243         rowptrs[i] = data + ((width * 4) * i);
    244     }
    245 
    246     png_read_image(p, rowptrs);
    247 
    248     png_destroy_read_struct(&p, &pi, 0);
    249     if(rowptrs != 0) free(rowptrs);
    250 
    251     *_width = width;
    252     *_height = height;
    253 
    254     return (void*) data;
    255 }
    256 
    257 
    258 #if 0
    259 int main(int argc, char **argv)
    260 {
    261     unsigned w,h;
    262     unsigned char *data;
    263 
    264     if(argc < 2) return 0;
    265 
    266 
    267     data = loadpng(argv[1], &w, &h);
    268 
    269     if(data != 0) {
    270         printf("w: %d  h: %d\n", w, h);
    271     }
    272 
    273     return 0;
    274 }
    275 #endif
    276