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