license some code GPL compatible to use in PCSX
[libpicofe.git] / common / readpng.c
CommitLineData
13059a60 1#include <stdio.h>
2#include <string.h>
3#include <png.h>
4#include "readpng.h"
c7a4ff64 5#include "lprintf.h"
13059a60 6
f6eaae4f 7int readpng(void *dest, const char *fname, readpng_what what, int req_w, int req_h)
13059a60 8{
9 FILE *fp;
10 png_structp png_ptr = NULL;
11 png_infop info_ptr = NULL;
12 png_bytepp row_ptr = NULL;
ff63afa1 13 int ret = -1;
13059a60 14
15 if (dest == NULL || fname == NULL)
16 {
ff63afa1 17 return -1;
13059a60 18 }
19
20 fp = fopen(fname, "rb");
21 if (fp == NULL)
22 {
c7a4ff64 23 lprintf(__FILE__ ": failed to open: %s\n", fname);
ff63afa1 24 return -1;
13059a60 25 }
26
27 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
28 if (!png_ptr)
29 {
c7a4ff64 30 lprintf(__FILE__ ": png_create_read_struct() failed\n");
13059a60 31 fclose(fp);
ff63afa1 32 return -1;
13059a60 33 }
34
35 info_ptr = png_create_info_struct(png_ptr);
36 if (!info_ptr)
37 {
c7a4ff64 38 lprintf(__FILE__ ": png_create_info_struct() failed\n");
13059a60 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 {
c7a4ff64 48 lprintf(__FILE__ ": png_get_rows() failed\n");
13059a60 49 goto done;
50 }
51
c7a4ff64 52 // lprintf("%s: %ix%i @ %ibpp\n", fname, (int)info_ptr->width, (int)info_ptr->height, info_ptr->pixel_depth);
13059a60 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 {
c7a4ff64 62 lprintf(__FILE__ ": bg image uses %ibpp, needed 24bpp\n", info_ptr->pixel_depth);
13059a60 63 break;
64 }
65 height = info_ptr->height;
f6eaae4f 66 if (height > req_h)
67 height = req_h;
13059a60 68 width = info_ptr->width;
f6eaae4f 69 if (width > req_w)
70 width = req_w;
13059a60 71
72 for (h = 0; h < height; h++)
73 {
74 unsigned char *src = row_ptr[h];
75 int len = width;
76 while (len--)
77 {
703e4c7b 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
13059a60 83 src += 3;
84 }
f6eaae4f 85 dst += req_w - width;
13059a60 86 }
87 break;
88 }
89
90 case READPNG_FONT:
91 {
92 int x, y, x1, y1;
93 unsigned char *dst = dest;
f6eaae4f 94 if (info_ptr->width != req_w || info_ptr->height != req_h)
13059a60 95 {
f6eaae4f 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);
13059a60 98 break;
99 }
100 if (info_ptr->pixel_depth != 8)
101 {
c7a4ff64 102 lprintf(__FILE__ ": font image uses %ibpp, needed 8bpp\n", info_ptr->pixel_depth);
13059a60 103 break;
104 }
105 for (y = 0; y < 16; y++)
106 {
107 for (x = 0; x < 16; x++)
108 {
f6eaae4f 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++)
13059a60 113 {
f6eaae4f 114 unsigned char *src = row_ptr[y*sym_h + y1] + x*sym_w;
115 for (x1 = sym_w/2; x1 > 0; x1--, src+=2)
13059a60 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;
f6eaae4f 127 if (info_ptr->width != req_w || info_ptr->height != req_h)
13059a60 128 {
f6eaae4f 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);
13059a60 131 break;
132 }
133 if (info_ptr->pixel_depth != 8)
134 {
c7a4ff64 135 lprintf(__FILE__ ": selector image uses %ibpp, needed 8bpp\n", info_ptr->pixel_depth);
13059a60 136 break;
137 }
f6eaae4f 138 for (y1 = 0; y1 < req_h; y1++)
13059a60 139 {
140 unsigned char *src = row_ptr[y1];
f6eaae4f 141 for (x1 = req_w/2; x1 > 0; x1--, src+=2)
13059a60 142 *dst++ = ((src[0]^0xff) & 0xf0) | ((src[1]^0xff) >> 4);
143 }
144 break;
145 }
ff63afa1 146
f6eaae4f 147 case READPNG_24:
ff63afa1 148 {
149 int height, width, h;
ff63afa1 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;
f6eaae4f 157 if (height > req_h)
158 height = req_h;
ff63afa1 159 width = info_ptr->width;
f6eaae4f 160 if (width > req_w)
161 width = req_w;
ff63afa1 162
163 for (h = 0; h < height; h++)
164 {
165 int len = width;
166 unsigned char *src = row_ptr[h];
f6eaae4f 167 dst += (req_w - width) * 3;
ff63afa1 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 }
13059a60 173 }
174
175
ff63afa1 176 ret = 0;
13059a60 177done:
178 png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : NULL, (png_infopp)NULL);
179 fclose(fp);
ff63afa1 180 return ret;
13059a60 181}
182
183