giz menu works
[picodrive.git] / platform / common / readpng.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <png.h>
4 #include "readpng.h"
5 #include "lprintf.h"
6
7 void readpng(void *dest, const char *fname, readpng_what what)
8 {
9         FILE *fp;
10         png_structp png_ptr = NULL;
11         png_infop info_ptr = NULL;
12         png_bytepp row_ptr = NULL;
13
14         if (dest == NULL || fname == NULL)
15         {
16                 return;
17         }
18
19         fp = fopen(fname, "rb");
20         if (fp == NULL)
21         {
22                 lprintf(__FILE__ ": failed to open: %s\n", fname);
23                 return;
24         }
25
26         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
27         if (!png_ptr)
28         {
29                 lprintf(__FILE__ ": png_create_read_struct() failed\n");
30                 fclose(fp);
31                 return;
32         }
33
34         info_ptr = png_create_info_struct(png_ptr);
35         if (!info_ptr)
36         {
37                 lprintf(__FILE__ ": png_create_info_struct() failed\n");
38                 goto done;
39         }
40
41         // Start reading
42         png_init_io(png_ptr, fp);
43         png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_PACKING, NULL);
44         row_ptr = png_get_rows(png_ptr, info_ptr);
45         if (row_ptr == NULL)
46         {
47                 lprintf(__FILE__ ": png_get_rows() failed\n");
48                 goto done;
49         }
50
51         // lprintf("%s: %ix%i @ %ibpp\n", fname, (int)info_ptr->width, (int)info_ptr->height, info_ptr->pixel_depth);
52
53         switch (what)
54         {
55                 case READPNG_BG:
56                 {
57                         int height, width, h;
58                         unsigned short *dst = dest;
59                         if (info_ptr->pixel_depth != 24)
60                         {
61                                 lprintf(__FILE__ ": bg image uses %ibpp, needed 24bpp\n", info_ptr->pixel_depth);
62                                 break;
63                         }
64                         height = info_ptr->height;
65                         if (height > 240) height = 240;
66                         width = info_ptr->width;
67                         if (width > 320) width = 320;
68
69                         for (h = 0; h < height; h++)
70                         {
71                                 unsigned char *src = row_ptr[h];
72                                 int len = width;
73                                 while (len--)
74                                 {
75                                         *dst++ = ((src[0]&0xf8)<<8) | ((src[1]&0xf8)<<3) | (src[2] >> 3);
76                                         src += 3;
77                                 }
78                                 dst += 320 - width;
79                         }
80                         break;
81                 }
82
83                 case READPNG_FONT:
84                 {
85                         int x, y, x1, y1;
86                         unsigned char *dst = dest;
87                         if (info_ptr->width != 128 || info_ptr->height != 160)
88                         {
89                                 lprintf(__FILE__ ": unexpected font image size %ix%i, needed 128x160\n",
90                                         (int)info_ptr->width, (int)info_ptr->height);
91                                 break;
92                         }
93                         if (info_ptr->pixel_depth != 8)
94                         {
95                                 lprintf(__FILE__ ": font image uses %ibpp, needed 8bpp\n", info_ptr->pixel_depth);
96                                 break;
97                         }
98                         for (y = 0; y < 16; y++)
99                         {
100                                 for (x = 0; x < 16; x++)
101                                 {
102                                         for (y1 = 0; y1 < 10; y1++)
103                                         {
104                                                 unsigned char *src = row_ptr[y*10 + y1] + x*8;
105                                                 for (x1 = 8/2; x1 > 0; x1--, src+=2)
106                                                         *dst++ = ((src[0]^0xff) & 0xf0) | ((src[1]^0xff) >> 4);
107                                         }
108                                 }
109                         }
110                         break;
111                 }
112
113                 case READPNG_SELECTOR:
114                 {
115                         int x1, y1;
116                         unsigned char *dst = dest;
117                         if (info_ptr->width != 8 || info_ptr->height != 10)
118                         {
119                                 lprintf(__FILE__ ": unexpected selector image size %ix%i, needed 8x10\n",
120                                         (int)info_ptr->width, (int)info_ptr->height);
121                                 break;
122                         }
123                         if (info_ptr->pixel_depth != 8)
124                         {
125                                 lprintf(__FILE__ ": selector image uses %ibpp, needed 8bpp\n", info_ptr->pixel_depth);
126                                 break;
127                         }
128                         for (y1 = 0; y1 < 10; y1++)
129                         {
130                                 unsigned char *src = row_ptr[y1];
131                                 for (x1 = 8/2; x1 > 0; x1--, src+=2)
132                                         *dst++ = ((src[0]^0xff) & 0xf0) | ((src[1]^0xff) >> 4);
133                         }
134                         break;
135                 }
136         }
137
138
139 done:
140         png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : NULL, (png_infopp)NULL);
141         fclose(fp);
142 }
143
144