1 /*
2 * OpenBOR - http://www.LavaLit.com
3 * -----------------------------------------------------------------------
4 * Licensed under the BSD license, see LICENSE in OpenBOR root for details.
5 *
6 * Copyright (c) 2004 - 2011 OpenBOR Team
7 */
8
9 #include <pspdisplay.h>
10 #include <stdlib.h>
11 #include <png.h>
12 #include "image.h"
13 #include "graphics.h"
14
getNextPower2(int width)15 static int getNextPower2(int width)
16 {
17 int b = width;
18 int n;
19 for(n = 0; b != 0; n++) b >>= 1;
20 b = 1 << n;
21 if(b == 2 * width) b >>= 1;
22 return b;
23 }
24
drawLine(int x0,int y0,int x1,int y1,int color,Color * destination,int width)25 static void drawLine(int x0, int y0, int x1, int y1, int color, Color* destination, int width)
26 {
27 int dy = y1 - y0;
28 int dx = x1 - x0;
29 int stepx, stepy;
30
31 if(dy < 0)
32 {
33 dy = -dy;
34 stepy = -width;
35 }
36 else stepy = width;
37
38 if(dx < 0)
39 {
40 dx = -dx;
41 stepx = -1;
42 }
43 else stepx = 1;
44
45 dy <<= 1;
46 dx <<= 1;
47
48 y0 *= width;
49 y1 *= width;
50 destination[x0+y0] = color;
51 if(dx > dy)
52 {
53 int fraction = dy - (dx >> 1);
54 while(x0 != x1)
55 {
56 if (fraction >= 0)
57 {
58 y0 += stepy;
59 fraction -= dx;
60 }
61 x0 += stepx;
62 fraction += dy;
63 destination[x0+y0] = color;
64 }
65 }
66 else
67 {
68 int fraction = dx - (dy >> 1);
69 while(y0 != y1)
70 {
71 if(fraction >= 0)
72 {
73 x0 += stepx;
74 fraction -= dy;
75 }
76 y0 += stepy;
77 fraction += dx;
78 destination[x0+y0] = color;
79 }
80 }
81 }
82
user_warning_fn(png_structp png_ptr,png_const_charp warning_msg)83 void user_warning_fn(png_structp png_ptr, png_const_charp warning_msg)
84 {
85 }
86
loadPNGImage(const char * filename)87 Image *loadPNGImage(const char* filename)
88 {
89 png_structp png_ptr;
90 png_infop info_ptr;
91 unsigned int sig_read = 0;
92 png_uint_32 width, height;
93 int bit_depth, color_type, interlace_type, x, y;
94 u32* line;
95 FILE *fp;
96
97 if((fp = fopen(filename, "rb")) == NULL) return NULL;
98 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
99 if(png_ptr == NULL)
100 {
101 fclose(fp);
102 return NULL;;
103 }
104 png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, user_warning_fn);
105 info_ptr = png_create_info_struct(png_ptr);
106 if(info_ptr == NULL)
107 {
108 fclose(fp);
109 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
110 return NULL;
111 }
112 if(setjmp(png_jmpbuf(png_ptr)))
113 {
114 fclose(fp);
115 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
116 return NULL;
117 }
118
119 png_init_io(png_ptr, fp);
120 png_set_sig_bytes(png_ptr, sig_read);
121 png_read_info(png_ptr, info_ptr);
122 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL);
123
124 png_set_strip_16(png_ptr);
125 png_set_packing(png_ptr);
126 if(color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);
127 if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr);
128 if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);
129 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
130
131 Image *image = createImage(width, height);
132 if(image == NULL)
133 {
134 fclose(fp);
135 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
136 return NULL;
137 }
138
139 line = (u32*)malloc(width * 4);
140 if(!line)
141 {
142 freeImage(image);
143 fclose(fp);
144 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
145 return NULL;
146 }
147 for(y=0; y<height; y++)
148 {
149 png_read_row(png_ptr, (u8*) line, png_bytep_NULL);
150 for(x=0; x<width; x++)
151 {
152 u32 color = line[x];
153 image->data[x + y * image->textureWidth] = color;
154 }
155 }
156 free(line);
157 png_read_end(png_ptr, info_ptr);
158 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
159 fclose(fp);
160 return image;
161 }
162
loadImage(const char * filename)163 Image* loadImage(const char* filename)
164 {
165 return loadPNGImage(filename);
166 }
167
savePNGImage(const char * filename)168 void savePNGImage(const char* filename)
169 {
170 u32* vram32;
171 u16* vram16;
172 int bufferwidth;
173 int pixelformat;
174 int sync = 0;
175 int i, x, y;
176 png_structp png_ptr;
177 png_infop info_ptr;
178 FILE* fp;
179 u8* line;
180
181 fp = fopen(filename, "wb");
182 if(!fp) return;
183 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
184 if(!png_ptr) return;
185 info_ptr = png_create_info_struct(png_ptr);
186 if(!info_ptr)
187 {
188 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
189 fclose(fp);
190 return;
191 }
192 png_init_io(png_ptr, fp);
193 png_set_IHDR(png_ptr, info_ptr, PSP_LCD_WIDTH, PSP_LCD_HEIGHT,
194 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
195 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
196 png_write_info(png_ptr, info_ptr);
197 line = (u8*)malloc(PSP_LCD_WIDTH * 3);
198 sceDisplayWaitVblankStart(); // if framebuf was set with PSP_LCD_SETBUF_NEXTFRAME, wait until it is changed
199 sceDisplayGetFrameBuf((void*)&vram32, &bufferwidth, &pixelformat, sync);
200 vram16 = (u16*)vram32;
201 for(y=0; y<PSP_LCD_HEIGHT; y++)
202 {
203 for(i=0, x=0; x<PSP_LCD_WIDTH; x++)
204 {
205 u32 color = 0;
206 u8 r = 0, g = 0, b = 0;
207 switch (pixelformat)
208 {
209 case PSP_DISPLAY_PIXEL_FORMAT_565:
210 color = vram16[x + y * bufferwidth];
211 r = (color & 0x1f) << 3;
212 g = ((color >> 5) & 0x3f) << 2 ;
213 b = ((color >> 11) & 0x1f) << 3 ;
214 break;
215 case PSP_DISPLAY_PIXEL_FORMAT_5551:
216 color = vram16[x + y * bufferwidth];
217 r = (color & 0x1f) << 3;
218 g = ((color >> 5) & 0x1f) << 3 ;
219 b = ((color >> 10) & 0x1f) << 3 ;
220 break;
221 case PSP_DISPLAY_PIXEL_FORMAT_4444:
222 color = vram16[x + y * bufferwidth];
223 r = (color & 0xf) << 4;
224 g = ((color >> 4) & 0xf) << 4 ;
225 b = ((color >> 8) & 0xf) << 4 ;
226 break;
227 case PSP_DISPLAY_PIXEL_FORMAT_8888:
228 color = vram32[x + y * bufferwidth];
229 r = color & 0xff;
230 g = (color >> 8) & 0xff;
231 b = (color >> 16) & 0xff;
232 break;
233 }
234 line[i++] = r;
235 line[i++] = g;
236 line[i++] = b;
237 }
238 png_write_row(png_ptr, line);
239 }
240 free(line);
241 line = NULL;
242 png_write_end(png_ptr, info_ptr);
243 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
244 fclose(fp);
245 }
246
saveImage(const char * filename)247 void saveImage(const char* filename)
248 {
249 savePNGImage(filename);
250 }
251
createImage(int width,int height)252 Image* createImage(int width, int height)
253 {
254 Image* image = (Image*) malloc(sizeof(Image));
255 if(!image) return NULL;
256 image->imageWidth = width;
257 image->imageHeight = height;
258 image->textureWidth = getNextPower2(width);
259 image->textureHeight = getNextPower2(height);
260 image->data = (Color*) memalign(16, image->textureWidth * image->textureHeight * sizeof(Color));
261 if(!image->data)
262 {
263 free(image);
264 image = NULL;
265 return NULL;
266 }
267 memset(image->data, 0, image->textureWidth * image->textureHeight * sizeof(Color));
268 return image;
269 }
270
freeImage(Image * image)271 void freeImage(Image* image)
272 {
273 free(image->data);
274 image->data = NULL;
275 free(image);
276 image = NULL;
277 }
278
clearImage(Image * image,Color color)279 void clearImage(Image* image, Color color)
280 {
281 int i;
282 int size = image->textureWidth * image->textureHeight;
283 Color* data = image->data;
284 for(i=0; i<size; i++, data++) *data = color;
285 }
286
putPixelToImage(Image * image,Color color,int x,int y)287 void putPixelToImage(Image* image, Color color, int x, int y)
288 {
289 image->data[x + y * image->textureWidth] = color;
290 }
291
getPixelFromImage(Image * image,int x,int y)292 Color getPixelFromImage(Image* image, int x, int y)
293 {
294 return image->data[x + y * image->textureWidth];
295 }
296
drawLineInImage(Image * image,Color color,int x0,int y0,int x1,int y1)297 void drawLineInImage(Image* image, Color color, int x0, int y0, int x1, int y1)
298 {
299 drawLine(x0, y0, x1, y1, color, image->data, image->textureWidth);
300 }
301
fillImageRect(Image * image,Color color,int x0,int y0,int width,int height)302 void fillImageRect(Image* image, Color color, int x0, int y0, int width, int height)
303 {
304 int skipX = image->textureWidth - width;
305 int x, y;
306 Color* data = image->data + x0 + y0 * image->textureWidth;
307 for(y=0; y<height; y++, data+=skipX)
308 {
309 for(x=0; x<width; x++, data++) *data = color;
310 }
311 }
312
fillImageEllipse(Image * image,Color color,int x0,int y0,int width,int height,int r)313 void fillImageEllipse(Image* image, Color color, int x0, int y0, int width, int height, int r)
314 {
315 int skipX = image->textureWidth - width;
316 int x, y;
317 Color* data = image->data + x0 + y0 * image->textureWidth;
318 for(y=0; y<height; y++, data+=skipX)
319 {
320 for(x=0; x<width; x++, data++)
321 {
322 if((x < r) && (y < r) && ((r-x)*(r-x)+(r-y)*(r-y) > r*r))
323 continue;
324 else if ((x < r) && (y > height-r-1) && ((r-x)*(r-x)+(y-height+r+1)*(y-height+r+1) > r*r))
325 continue;
326 else if ((x > width-r-1) && (y < r) && ((x-width+r+1)*(x-width+r+1)+(r-y)*(r-y) > r*r))
327 continue;
328 else if ((x > width-r-1) && (y > height-r-1) && ((x-width+r+1)*(x-width+r+1)+(y-height+r+1)*(y-height+r+1) > r*r))
329 continue;
330 else
331 *data = color;
332 }
333 }
334 }
335
copyImageToImage(int sx,int sy,int width,int height,Image * source,int dx,int dy,Image * destination)336 void copyImageToImage(int sx, int sy, int width, int height, Image* source, int dx, int dy, Image* destination)
337 {
338 Color* destinationData = &destination->data[destination->textureWidth * dy + dx];
339 int destinationSkipX = destination->textureWidth - width;
340 Color* sourceData = &source->data[source->textureWidth * sy + sx];
341 int sourceSkipX = source->textureWidth - width;
342 int x, y;
343 for(y=0; y<height; y++, destinationData+=destinationSkipX, sourceData+=sourceSkipX)
344 {
345 for(x=0; x<width; x++, destinationData++, sourceData++) *destinationData = *sourceData;
346 }
347 }
348
drawImageBox(Image * source,Color background,Color border,int borderwidth)349 void drawImageBox(Image *source, Color background, Color border, int borderwidth)
350 {
351 fillImageRect(source, background, 0, 0, source->imageWidth, source->imageHeight);
352 int i, x = source->imageWidth - 1, y = source->imageHeight - 1;
353 for(i=0; i<borderwidth; i++)
354 {
355 drawLineInImage(source, border, i, i, x, i); // Top
356 drawLineInImage(source, border, i, y - i, x, y - i); // Bottom
357 drawLineInImage(source, border, i, i, i, y); // Left
358 drawLineInImage(source, border, x - i, i, x - i, y - i); // Right
359 }
360 }