1 #include <l4/libpng/l4png_wrap.h>
2 #include <l4/sys/l4int.h>
9 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
18 #define u16 unsigned short
20 #define PNG_BYTES_TO_CHECK 4
21 #define PNG_ROW_MEM_SIZE 8
24 static int check_if_png(char *png_data)
27 char buf[PNG_BYTES_TO_CHECK];
29 for (i=0; i<PNG_BYTES_TO_CHECK; i++)
32 /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
33 Return nonzero (true) if they match */
35 return png_sig_cmp((unsigned char *)buf, (png_size_t)0, PNG_BYTES_TO_CHECK);
39 struct l4png_wrap_read_func_struct {
46 l4png_wrap_read_func_from_memory(png_structp png_ptr, png_bytep data,
50 l4png_wrap_read_func_from_memory(png_structp png_ptr, png_bytep data,
53 struct l4png_wrap_read_func_struct *a
54 = (struct l4png_wrap_read_func_struct *)png_ptr->io_ptr;
58 if (a->offset + length > a->size)
59 png_error(png_ptr, "read too much");
61 memcpy(data, a->mem + a->offset, length);
65 enum mode_t { M_MEMORY, M_FILE };
67 static int __internal_png_get_size(enum mode_t mode,
68 void *png_data, int png_data_size,
70 int *width, int *height)
74 struct l4png_wrap_read_func_struct memio;
76 /* check if png_data really contains a png image */
79 if (check_if_png(png_data))
83 /* create png read struct */
84 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
92 memio.size = png_data_size;
94 png_set_read_fn(png_ptr, &memio, l4png_wrap_read_func_from_memory);
97 /* create png info struct */
98 info_ptr = png_create_info_struct(png_ptr);
102 png_destroy_read_struct(&png_ptr, NULL, NULL);
106 if (setjmp(png_jmpbuf(png_ptr)))
108 /* Free all of the memory associated with the png_ptr and info_ptr */
109 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
111 /* If we get here, we had a problem reading the file */
112 return LIBPNG_EDAMAGEDPNG;
115 if (mode == M_MEMORY)
116 png_init_io(png_ptr,(png_FILE_p) &memio);
118 png_init_io(png_ptr,(png_FILE_p) fp);
120 /* read info struct */
121 png_read_info(png_ptr, info_ptr);
123 *width = png_get_image_width(png_ptr,info_ptr);
124 *height = png_get_image_height(png_ptr,info_ptr);
126 /* free mem of png structs */
127 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
132 int libpng_get_size_mem(void *png_data, int png_data_size,
133 int *width, int *height)
135 return __internal_png_get_size(M_MEMORY, png_data, png_data_size, NULL,
139 int libpng_get_size_file(const char *filename, int *width, int *height)
144 if (!(fp = fopen(filename, "rb")))
147 r = __internal_png_get_size(M_FILE, NULL, 0, fp, width, height);
153 #define DITHER_SIZE 16
155 static const int dither_matrix[DITHER_SIZE][DITHER_SIZE] = {
156 { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
157 { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
158 { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
159 { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
160 { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
161 { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
162 { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
163 { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
164 { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
165 { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
166 { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
167 { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
168 { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
169 { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
170 { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
171 { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
176 convert_line_24to16(unsigned char *src, short *dst, int width, int line)
179 int const *dm = dither_matrix[line & 0xf];
181 /* calculate 16bit RGB value and copy it to destination buffer */
182 for (j = 0; j < width; j++)
185 r = (int)(*(src++)) + (v >> 5);
186 g = (int)(*(src++)) + (v >> 6);
187 b = (int)(*(src++)) + (v >> 5);
194 *(dst + j) = ((r & 0xf8) << 8) + ((g & 0xfc) << 3) + ((b & 0xf8) >> 3);
203 convert_pixel_from_rgb888(unsigned srcval, void *dst, l4re_video_view_info_t *fbi)
207 v = ((srcval >> (8 - fbi->pixel_info.r.size)) & ((1 << fbi->pixel_info.r.size) - 1)) << fbi->pixel_info.r.shift;
208 v |= ((srcval >> (16 - fbi->pixel_info.g.size)) & ((1 << fbi->pixel_info.g.size) - 1)) << fbi->pixel_info.g.shift;
209 v |= ((srcval >> (24 - fbi->pixel_info.b.size)) & ((1 << fbi->pixel_info.b.size) - 1)) << fbi->pixel_info.b.shift;
211 //printf("srcval=%08x v=%08x dst=%p bpl=%d\n", srcval, v, dst, fbi->bytes_per_line);
212 switch (fbi->pixel_info.bytes_per_pixel)
215 *(unsigned char *)dst = v;
218 *(unsigned short *)dst = v;
220 #if defined(ARCH_x86) || defined(ARCH_amd64)
222 *(unsigned short *)(dst + 0) = v & 0xffff;
223 *(unsigned char *)(dst + 2) = v >> 16;
227 *(unsigned int *)dst = v;
230 printf("unhandled bitsperpixel %d\n",
231 l4re_video_bits_per_pixel(&fbi->pixel_info));
237 internal_render(enum mode_t mode, void *png_data, char * const dst,
238 int png_data_size, unsigned dst_buf_size,
239 l4re_video_view_info_t *dst_descr, FILE *fp)
243 png_uint_32 width, height;
244 unsigned char *row_ptr;
246 int bit_depth, color_type, interlace_type;
247 struct l4png_wrap_read_func_struct memio;
249 /* check if png_data really contains a png image */
250 if (mode == M_MEMORY && check_if_png((char *)png_data))
251 return LIBPNG_ENOPNG;
253 /* create png read struct */
254 png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL,
258 printf("error during creation of png read struct");
262 if (mode == M_MEMORY)
264 memio.mem = png_data;
265 memio.size = png_data_size;
267 png_set_read_fn(png_ptr, &memio, l4png_wrap_read_func_from_memory);
270 /* create png info struct */
271 info_ptr = png_create_info_struct(png_ptr);
275 png_destroy_read_struct(&png_ptr, NULL, NULL);
276 printf("error during creation of png info struct");
280 if (setjmp(png_jmpbuf(png_ptr)))
282 /* Free all of the memory associated with the png_ptr and info_ptr */
283 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
285 /* If we are here, we had a problem reading the image */
286 return LIBPNG_EDAMAGEDPNG;
289 if (mode == M_MEMORY)
290 png_init_io(png_ptr,(png_FILE_p)&memio);
292 png_init_io(png_ptr,(png_FILE_p)fp);
294 /* read info struct */
295 png_read_info(png_ptr, info_ptr);
297 /* get image data chunk */
298 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
299 &interlace_type, NULL, NULL);
302 printf("bit_depth: %d, color_type: %d, width: %d, height: %d",
303 bit_depth, color_type, width, height);
305 if (dst_buf_size < height * dst_descr->bytes_per_line)
307 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
308 return LIBPNG_ARGB_BUF_TO_SMALL;
311 if (color_type == PNG_COLOR_TYPE_PALETTE)
312 png_set_palette_to_rgb(png_ptr);
314 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
315 png_set_expand_gray_1_2_4_to_8(png_ptr);
317 if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
318 png_set_gray_to_rgb(png_ptr);
321 png_set_packing(png_ptr);
323 /* set down to 8bit value */
325 png_set_strip_16(png_ptr);
327 if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
328 png_set_strip_alpha(png_ptr);
330 row_ptr = malloc(png_get_rowbytes(png_ptr, info_ptr) * PNG_ROW_MEM_SIZE);
334 printf("not enough memory for a png row");
338 if (dst_descr->pixel_info.bytes_per_pixel == 2)
341 // special case for 16bit, with dithering
342 if (interlace_type == PNG_INTERLACE_NONE)
343 for (row = 0; row < height; row++)
345 png_read_row(png_ptr, (png_bytep)row_ptr, NULL);
346 convert_line_24to16(row_ptr, (short *)_dst, width, row);
347 _dst += dst_descr->bytes_per_line;
352 png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
354 for (row = 0; row < height; row++)
356 png_read_row(png_ptr, (png_bytep)row_ptr, NULL);
357 unsigned *r = (unsigned *)row_ptr;
359 for (unsigned j = 0; j < width;
360 ++j, ++r, o += dst_descr->pixel_info.bytes_per_pixel)
361 convert_pixel_from_rgb888(*r >> 8, _dst + o, dst_descr);
363 _dst += dst_descr->bytes_per_line;
369 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
374 int libpng_render_mem(void *png_data, void *dst_buf,
375 unsigned png_data_size, unsigned dst_size,
376 l4re_video_view_info_t *dst_descr)
378 return internal_render(M_MEMORY, png_data, dst_buf,
379 png_data_size, dst_size,
383 int libpng_render_file(const char *filename, void *dst_buf,
385 l4re_video_view_info_t *dst_descr)
390 if (!(fp = fopen(filename, "rb")))
393 r = internal_render(M_MEMORY, 0, dst_buf, 0, dst_size, dst_descr, fp);