1 #include <l4/libpng/l4png_wrap.h>
2 #include <l4/libpng/png.h>
4 #include <l4/sys/l4int.h>
7 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
16 #define u16 unsigned short
18 #define PNG_BYTES_TO_CHECK 4
19 #define PNG_ROW_MEM_SIZE 8
22 static int check_if_png(char *png_data)
25 char buf[PNG_BYTES_TO_CHECK];
27 for (i=0; i<PNG_BYTES_TO_CHECK; i++)
30 /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
31 Return nonzero (true) if they match */
33 return png_sig_cmp((unsigned char *)buf, (png_size_t)0, PNG_BYTES_TO_CHECK);
37 struct l4png_wrap_read_func_struct {
44 l4png_wrap_read_func_from_memory(png_structp png_ptr, png_bytep data,
48 l4png_wrap_read_func_from_memory(png_structp png_ptr, png_bytep data,
51 struct l4png_wrap_read_func_struct *a
52 = (struct l4png_wrap_read_func_struct *)png_ptr->io_ptr;
56 if (a->offset + length > a->size)
57 png_error(png_ptr, "read too much");
59 memcpy(data, a->mem + a->offset, length);
63 enum mode_t { M_MEMORY, M_FILE };
65 static int __internal_png_get_size(enum mode_t mode,
66 void *png_data, int png_data_size,
68 int *width, int *height)
72 struct l4png_wrap_read_func_struct memio;
74 /* check if png_data really contains a png image */
77 if (check_if_png(png_data))
81 /* create png read struct */
82 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
90 memio.size = png_data_size;
92 png_set_read_fn(png_ptr, &memio, l4png_wrap_read_func_from_memory);
95 /* create png info struct */
96 info_ptr = png_create_info_struct(png_ptr);
100 png_destroy_read_struct(&png_ptr, NULL, NULL);
104 if (setjmp(png_jmpbuf(png_ptr)))
106 /* Free all of the memory associated with the png_ptr and info_ptr */
107 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
109 /* If we get here, we had a problem reading the file */
113 if (mode == M_MEMORY)
114 png_init_io(png_ptr,(png_FILE_p) &memio);
116 png_init_io(png_ptr,(png_FILE_p) fp);
118 /* read info struct */
119 png_read_info(png_ptr, info_ptr);
121 *width = png_get_image_width(png_ptr,info_ptr);
122 *height = png_get_image_height(png_ptr,info_ptr);
124 /* free mem of png structs */
125 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
130 int png_get_size_mem(void *png_data, int png_data_size,
131 int *width, int *height)
133 return __internal_png_get_size(M_MEMORY, png_data, png_data_size, NULL,
137 int png_get_size_file(const char *filename, int *width, int *height)
142 if (!(fp = fopen(filename, "rb")))
145 r = __internal_png_get_size(M_FILE, NULL, 0, fp, width, height);
151 static int __internal_png_convert_ARGB
152 (enum mode_t mode, void *png_data, void *argb_buf,
153 int png_data_size, unsigned argb_max_size, FILE *fp)
157 png_uint_32 width, height;
158 char *row_ptr, *row_ptr_backup, *dst;
160 int bit_depth, color_type, interlace_type, a, r, g, b, offset;
161 struct l4png_wrap_read_func_struct memio;
163 if (mode == M_MEMORY)
164 /* check if png_data really contains a png image */
165 if(check_if_png((char *)png_data)) return ENOPNG;
169 /* create png read struct */
170 png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL,
176 if (mode == M_MEMORY)
178 memio.mem = png_data;
179 memio.size = png_data_size;
181 png_set_read_fn(png_ptr, &memio, l4png_wrap_read_func_from_memory);
184 /* create png info struct */
185 info_ptr = png_create_info_struct(png_ptr);
187 if (info_ptr==NULL) {
188 png_destroy_read_struct(&png_ptr, NULL, NULL);
192 if (setjmp(png_jmpbuf(png_ptr)))
194 /* Free all of the memory associated with the png_ptr and info_ptr */
195 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
197 /* If we get here, we had a problem reading the file */
201 dst = (char *) argb_buf;
203 if (mode == M_MEMORY)
204 png_init_io(png_ptr,(png_FILE_p) &memio);
206 png_init_io(png_ptr,(png_FILE_p) fp);
208 /* read info struct */
209 png_read_info(png_ptr, info_ptr);
211 /* get image data chunk */
212 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
213 &interlace_type, NULL, NULL);
215 if (argb_max_size < height*width*offset) {
216 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
217 return ARGB_BUF_TO_SMALL;
220 if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);
222 /* set down to 8bit value */
223 if (bit_depth == 16) png_set_strip_16(png_ptr);
225 /* normally png files have rgba format now swap it into argb */
226 if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_swap_alpha(png_ptr);
227 else png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
229 row_ptr = malloc(png_get_rowbytes(png_ptr,info_ptr)*PNG_ROW_MEM_SIZE);
231 if (row_ptr == NULL) {
232 printf("not enough memory for a png row");
236 row_ptr_backup = row_ptr;
238 for (row = 0;row<height-1;row++) {
240 /* backup row pointer to start address */
241 row_ptr = row_ptr_backup;
243 /* read a single row */
244 png_read_row(png_ptr, (png_bytep)row_ptr, NULL);
246 /* calculate ARGB value and copy it to destination buffer */
247 for (j=0;j<width;j++) {
253 *(dst+j*offset+1) = r;
254 *(dst+j*offset+2) = g;
255 *(dst+j*offset+3) = b;
260 /* free mem of png structs */
261 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
267 int png_convert_ARGB_mem(void *png_data, void *argb_buf,
268 int png_data_size, unsigned argb_max_size)
270 return __internal_png_convert_ARGB(M_MEMORY, png_data, argb_buf,
271 png_data_size, argb_max_size, NULL);
274 int png_convert_ARGB_file(const char *filename, void *argb_buf,
275 unsigned argb_max_size)
280 if (!(fp = fopen(filename, "rb")))
283 r = __internal_png_convert_ARGB(M_FILE, 0, argb_buf,
284 0, argb_max_size, fp);
291 #define DITHER_SIZE 16
293 static const int dither_matrix[DITHER_SIZE][DITHER_SIZE] = {
294 { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
295 { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
296 { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
297 { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
298 { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
299 { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
300 { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
301 { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
302 { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
303 { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
304 { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
305 { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
306 { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
307 { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
308 { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
309 { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
313 static inline void convert_24to16(unsigned char *src, short *dst, int width, int line)
316 int const *dm = dither_matrix[line & 0xf];
318 /* calculate 16bit RGB value and copy it to destination buffer */
319 for (j=0;j<width;j++) {
321 r = (int)(*(src++)) + (v>>5);
322 g = (int)(*(src++)) + (v>>6);
323 b = (int)(*(src++)) + (v>>5);
327 *(dst+j) = ((r&0xf8)<<8) + ((g&0xfc)<<3) + ((b&0xf8)>>3);
332 static int __internal_png_convert_RGB16bit
333 (enum mode_t mode, void *png_data, void *argb_buf, int png_data_size,
334 unsigned argb_max_size, int line_offset, FILE *fp)
338 png_uint_32 width, height;
339 unsigned char *row_ptr, *row_ptr_backup;
341 int bit_depth, color_type, interlace_type;
343 struct l4png_wrap_read_func_struct memio;
345 /* check if png_data really contains a png image */
346 if (mode == M_MEMORY)
347 if(check_if_png((char *)png_data)) return ENOPNG;
349 /* create png read struct */
350 png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL,
354 printf("error during creation of png read struct");
358 if (mode == M_MEMORY)
360 memio.mem = png_data;
361 memio.size = png_data_size;
363 png_set_read_fn(png_ptr, &memio, l4png_wrap_read_func_from_memory);
367 /* create png info struct */
368 info_ptr = png_create_info_struct(png_ptr);
370 if (info_ptr==NULL) {
371 png_destroy_read_struct(&png_ptr, NULL, NULL);
372 printf("error during creation of png info struct");
376 if (setjmp(png_jmpbuf(png_ptr)))
378 /* Free all of the memory associated with the png_ptr and info_ptr */
379 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
381 /* If we are here, we had a problem reading the image */
385 dst = (unsigned short *) argb_buf;
387 if (mode == M_MEMORY)
388 png_init_io(png_ptr,(png_FILE_p)&memio);
390 png_init_io(png_ptr,(png_FILE_p)fp);
392 /* read info struct */
393 png_read_info(png_ptr, info_ptr);
395 /* get image data chunk */
396 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
397 &interlace_type, NULL, NULL);
400 printf("bit_depth: %d, color_type: %d, width: %d, height: %d",
401 bit_depth, color_type, width, height);
403 if (argb_max_size < height*width*sizeof(u16)) {
405 /* Free all of the memory associated with the png_ptr and info_ptr */
406 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
408 return ARGB_BUF_TO_SMALL;
411 if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);
413 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
414 png_set_expand_gray_1_2_4_to_8(png_ptr);
416 if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
417 png_set_gray_to_rgb(png_ptr);
419 if (bit_depth < 8) png_set_packing(png_ptr);
421 /* set down to 8bit value */
422 if (bit_depth == 16) png_set_strip_16(png_ptr);
424 if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_strip_alpha(png_ptr);
426 row_ptr = malloc(png_get_rowbytes(png_ptr,info_ptr)*PNG_ROW_MEM_SIZE);
428 if (row_ptr == NULL) {
429 printf("not enough memory for a png row");
433 row_ptr_backup = row_ptr;
435 if (interlace_type == PNG_INTERLACE_NONE) {
437 for (row = 0;row<height-1;row++) {
439 /* backup row pointer to start address */
440 row_ptr = row_ptr_backup;
442 /* read a single row */
443 png_read_row(png_ptr, (png_bytep)row_ptr, NULL);
445 convert_24to16(row_ptr, (short *)dst, width, row);
446 // /* calculate 16bit RGB value and copy it to destination buffer */
447 // for (j=0;j<width;j++) {
451 // *(dst+j) = ((r&0xf8)<<8) + ((g&0xfc)<<3) + ((b&0xf8)>>3);
457 /* free old row pointer */
458 free(row_ptr_backup);
462 /* free mem of png structs */
463 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
468 int png_convert_RGB16bit_mem(void *png_data, void *argb_buf, int png_data_size,
469 unsigned argb_max_size, int line_offset)
471 return __internal_png_convert_RGB16bit(M_MEMORY, png_data, argb_buf,
472 png_data_size, argb_max_size,
476 int png_convert_RGB16bit_file(const char *filename, void *argb_buf,
477 unsigned argb_max_size, int line_offset)
482 if (!(fp = fopen(filename, "rb")))
485 r = __internal_png_convert_RGB16bit(M_FILE, 0, argb_buf,
486 0, argb_max_size, line_offset, fp);