psp port runs, bad colors
[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 #ifdef PSP
84                                         *dst++ = ((src[2]&0xf8)<<8) | ((src[1]&0xf8)<<3) | (src[0] >> 3); // BGR
85 #else
86                                         *dst++ = ((src[0]&0xf8)<<8) | ((src[1]&0xf8)<<3) | (src[2] >> 3); // RGB
87 #endif
88                                         src += 3;
89                                 }
90                                 dst += BG_WIDTH - width;
91                         }
92                         break;
93                 }
94
95                 case READPNG_FONT:
96                 {
97                         int x, y, x1, y1;
98                         unsigned char *dst = dest;
99                         if (info_ptr->width != 128 || info_ptr->height != 160)
100                         {
101                                 lprintf(__FILE__ ": unexpected font image size %ix%i, needed 128x160\n",
102                                         (int)info_ptr->width, (int)info_ptr->height);
103                                 break;
104                         }
105                         if (info_ptr->pixel_depth != 8)
106                         {
107                                 lprintf(__FILE__ ": font image uses %ibpp, needed 8bpp\n", info_ptr->pixel_depth);
108                                 break;
109                         }
110                         for (y = 0; y < 16; y++)
111                         {
112                                 for (x = 0; x < 16; x++)
113                                 {
114                                         for (y1 = 0; y1 < 10; y1++)
115                                         {
116                                                 unsigned char *src = row_ptr[y*10 + y1] + x*8;
117                                                 for (x1 = 8/2; x1 > 0; x1--, src+=2)
118                                                         *dst++ = ((src[0]^0xff) & 0xf0) | ((src[1]^0xff) >> 4);
119                                         }
120                                 }
121                         }
122                         break;
123                 }
124
125                 case READPNG_SELECTOR:
126                 {
127                         int x1, y1;
128                         unsigned char *dst = dest;
129                         if (info_ptr->width != 8 || info_ptr->height != 10)
130                         {
131                                 lprintf(__FILE__ ": unexpected selector image size %ix%i, needed 8x10\n",
132                                         (int)info_ptr->width, (int)info_ptr->height);
133                                 break;
134                         }
135                         if (info_ptr->pixel_depth != 8)
136                         {
137                                 lprintf(__FILE__ ": selector image uses %ibpp, needed 8bpp\n", info_ptr->pixel_depth);
138                                 break;
139                         }
140                         for (y1 = 0; y1 < 10; y1++)
141                         {
142                                 unsigned char *src = row_ptr[y1];
143                                 for (x1 = 8/2; x1 > 0; x1--, src+=2)
144                                         *dst++ = ((src[0]^0xff) & 0xf0) | ((src[1]^0xff) >> 4);
145                         }
146                         break;
147                 }
148         }
149
150
151 done:
152         png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : NULL, (png_infopp)NULL);
153         fclose(fp);
154 }
155
156