tweaking pandora frontend
[libpicofe.git] / common / readpng.c
... / ...
CommitLineData
1#include <stdio.h>
2#include <string.h>
3#include <png.h>
4#include "readpng.h"
5#include "lprintf.h"
6
7int readpng(void *dest, const char *fname, readpng_what what, int req_w, int req_h)
8{
9 FILE *fp;
10 png_structp png_ptr = NULL;
11 png_infop info_ptr = NULL;
12 png_bytepp row_ptr = NULL;
13 int ret = -1;
14
15 if (dest == NULL || fname == NULL)
16 {
17 return -1;
18 }
19
20 fp = fopen(fname, "rb");
21 if (fp == NULL)
22 {
23 lprintf(__FILE__ ": failed to open: %s\n", fname);
24 return -1;
25 }
26
27 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
28 if (!png_ptr)
29 {
30 lprintf(__FILE__ ": png_create_read_struct() failed\n");
31 fclose(fp);
32 return -1;
33 }
34
35 info_ptr = png_create_info_struct(png_ptr);
36 if (!info_ptr)
37 {
38 lprintf(__FILE__ ": png_create_info_struct() failed\n");
39 goto done;
40 }
41
42 // Start reading
43 png_init_io(png_ptr, fp);
44 png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_PACKING, NULL);
45 row_ptr = png_get_rows(png_ptr, info_ptr);
46 if (row_ptr == NULL)
47 {
48 lprintf(__FILE__ ": png_get_rows() failed\n");
49 goto done;
50 }
51
52 // lprintf("%s: %ix%i @ %ibpp\n", fname, (int)info_ptr->width, (int)info_ptr->height, info_ptr->pixel_depth);
53
54 switch (what)
55 {
56 case READPNG_BG:
57 {
58 int height, width, h;
59 unsigned short *dst = dest;
60 if (info_ptr->pixel_depth != 24)
61 {
62 lprintf(__FILE__ ": bg image uses %ibpp, needed 24bpp\n", info_ptr->pixel_depth);
63 break;
64 }
65 height = info_ptr->height;
66 if (height > req_h)
67 height = req_h;
68 width = info_ptr->width;
69 if (width > req_w)
70 width = req_w;
71
72 for (h = 0; h < height; h++)
73 {
74 unsigned char *src = row_ptr[h];
75 int len = width;
76 while (len--)
77 {
78#ifdef PSP
79 *dst++ = ((src[2]&0xf8)<<8) | ((src[1]&0xf8)<<3) | (src[0] >> 3); // BGR
80#else
81 *dst++ = ((src[0]&0xf8)<<8) | ((src[1]&0xf8)<<3) | (src[2] >> 3); // RGB
82#endif
83 src += 3;
84 }
85 dst += req_w - width;
86 }
87 break;
88 }
89
90 case READPNG_FONT:
91 {
92 int x, y, x1, y1;
93 unsigned char *dst = dest;
94 if (info_ptr->width != req_w || info_ptr->height != req_h)
95 {
96 lprintf(__FILE__ ": unexpected font image size %dx%d, needed %dx%d\n",
97 (int)info_ptr->width, (int)info_ptr->height, req_w, req_h);
98 break;
99 }
100 if (info_ptr->pixel_depth != 8)
101 {
102 lprintf(__FILE__ ": font image uses %ibpp, needed 8bpp\n", info_ptr->pixel_depth);
103 break;
104 }
105 for (y = 0; y < 16; y++)
106 {
107 for (x = 0; x < 16; x++)
108 {
109 /* 16x16 grid of syms */
110 int sym_w = req_w / 16;
111 int sym_h = req_h / 16;
112 for (y1 = 0; y1 < sym_h; y1++)
113 {
114 unsigned char *src = row_ptr[y*sym_h + y1] + x*sym_w;
115 for (x1 = sym_w/2; x1 > 0; x1--, src+=2)
116 *dst++ = ((src[0]^0xff) & 0xf0) | ((src[1]^0xff) >> 4);
117 }
118 }
119 }
120 break;
121 }
122
123 case READPNG_SELECTOR:
124 {
125 int x1, y1;
126 unsigned char *dst = dest;
127 if (info_ptr->width != req_w || info_ptr->height != req_h)
128 {
129 lprintf(__FILE__ ": unexpected selector image size %ix%i, needed %dx%d\n",
130 (int)info_ptr->width, (int)info_ptr->height, req_w, req_h);
131 break;
132 }
133 if (info_ptr->pixel_depth != 8)
134 {
135 lprintf(__FILE__ ": selector image uses %ibpp, needed 8bpp\n", info_ptr->pixel_depth);
136 break;
137 }
138 for (y1 = 0; y1 < req_h; y1++)
139 {
140 unsigned char *src = row_ptr[y1];
141 for (x1 = req_w/2; x1 > 0; x1--, src+=2)
142 *dst++ = ((src[0]^0xff) & 0xf0) | ((src[1]^0xff) >> 4);
143 }
144 break;
145 }
146
147 case READPNG_24:
148 {
149 int height, width, h;
150 unsigned char *dst = dest;
151 if (info_ptr->pixel_depth != 24)
152 {
153 lprintf(__FILE__ ": image uses %ibpp, needed 24bpp\n", info_ptr->pixel_depth);
154 break;
155 }
156 height = info_ptr->height;
157 if (height > req_h)
158 height = req_h;
159 width = info_ptr->width;
160 if (width > req_w)
161 width = req_w;
162
163 for (h = 0; h < height; h++)
164 {
165 int len = width;
166 unsigned char *src = row_ptr[h];
167 dst += (req_w - width) * 3;
168 for (len = width; len > 0; len--, dst+=3, src+=3)
169 dst[0] = src[2], dst[1] = src[1], dst[2] = src[0];
170 }
171 break;
172 }
173 }
174
175
176 ret = 0;
177done:
178 png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : NULL, (png_infopp)NULL);
179 fclose(fp);
180 return ret;
181}
182
183