2 +----------------------------------------------------------------------+
3 | Author: yoya@awm.jp |
4 +----------------------------------------------------------------------+
9 #include "swf_define.h"
14 #include "bitstream.h"
15 #include "swf_rgb.h" // Lossless format=3
16 #include "swf_rgba.h" // Lossless2 format=3
17 #include "swf_xrgb.h" // Lossless format=5
18 #include "swf_argb.h" // Lossless2 format=5
21 typedef struct my_png_buffer_ {
23 unsigned long data_len;
24 unsigned long data_offset;
32 png_data_read_func(png_structp png_ptr, png_bytep buf, png_size_t size) {
33 my_png_buffer *png_buff = (my_png_buffer *)png_get_io_ptr(png_ptr);
34 if (png_buff->data_offset + size <= png_buff->data_len) {
35 memcpy(buf, png_buff->data + png_buff->data_offset, size);
36 png_buff->data_offset += size;
38 fprintf(stderr, "png_data_read_func: ! png_buff->data_offset(%lu) + size(%zd) <= png_buff->data_len(%lu)\n",
39 png_buff->data_offset, size, png_buff->data_len);
40 png_error(png_ptr,"png_read_read_func failed");
44 static void png_data_read(png_structp png_ptr, my_png_buffer *png_buff) {
45 png_set_read_fn(png_ptr, (png_voidp) png_buff,
46 (png_rw_ptr)png_data_read_func);
54 png_data_write_func(png_structp png_ptr, png_bytep buf, png_size_t size) {
55 my_png_buffer *png_buff = (my_png_buffer *)png_get_io_ptr(png_ptr);
56 unsigned long new_data_len;
58 if (png_buff->data_offset + size > png_buff->data_len) {
59 new_data_len = 2 * png_buff->data_len;
60 if (png_buff->data_offset + size > new_data_len) {
61 new_data_len = png_buff->data_offset + size;
63 tmp = realloc(png_buff->data, new_data_len);
65 fprintf(stderr, "png_data_write_func: can't realloc: new_data_len(%lu), data_len(%lu)\n",
66 new_data_len, png_buff->data_len);
67 png_error(png_ptr,"png_data_write_func failed");
70 png_buff->data_len = new_data_len;
72 memcpy(png_buff->data + png_buff->data_offset, buf, size);
73 png_buff->data_offset += size;
77 png_data_write(png_structp png_ptr, my_png_buffer *png_buff) {
78 png_set_write_fn(png_ptr, (png_voidp) png_buff,
79 (png_rw_ptr)png_data_write_func, NULL);
87 pngconv_png2lossless(unsigned char *png_data, unsigned long png_data_len,
88 int *tag_no, int *format,
89 unsigned short *width, unsigned short *height,
90 void **colormap, int *colormap_count, int rgb15) {
91 volatile png_structp png_ptr = NULL;
92 volatile png_infop png_info_ptr = NULL;
93 my_png_buffer png_buff;
95 png_uint_32 png_width = 0, png_height = 0;
96 volatile png_bytepp png_image_data = NULL;
97 register png_uint_32 x, y;
98 void *image_data = NULL;
99 png_color *palette = NULL;
101 png_bytep trans = NULL;
103 png_color_16p trans_values = NULL;
105 if (png_data == NULL) {
106 fprintf(stderr, "pngconv_png2lossless: png_data == NULL\n");
109 if (png_sig_cmp((png_bytep)png_data, 0, 8)) { // bad signature
110 fprintf(stderr, "pngconv_png2lossless: is not PNG!\n");
113 png_ptr = png_create_read_struct
114 (PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
116 fprintf(stderr, "pngconv_png2lossless: can't create read_struct\n");
119 if (setjmp(png_jmpbuf(png_ptr))) {
120 fprintf(stderr, "pngconv_png2lossless: libpng error jump occured\n");
121 png_destroy_read_struct((png_structpp) &png_ptr,
122 (png_infopp) &png_info_ptr, NULL);
123 if (png_image_data) {
124 for (y=0 ; y < png_height ; y++) {
125 free(png_image_data[y]);
127 free(png_image_data);
131 png_info_ptr = png_create_info_struct(png_ptr);
132 if (! png_info_ptr) {
133 fprintf(stderr, "pngconv_png2lossless: can't create info_struct\n");
134 png_destroy_read_struct ((png_structpp)&png_ptr, NULL, NULL);
137 png_buff.data = png_data;
138 png_buff.data_len = png_data_len;
139 png_buff.data_offset = 0;
141 png_data_read(png_ptr, &png_buff);
142 png_read_info(png_ptr, png_info_ptr);
143 png_get_IHDR(png_ptr, png_info_ptr,
144 &png_width, &png_height, &bpp, &color_type,
146 *width = (unsigned short) png_width;
147 *height = (unsigned short) png_height;
149 if ((rgb15 > 0) && (color_type != PNG_COLOR_TYPE_RGB)) { // warning
150 fprintf(stderr, "rgb15 is %d but color_type is not PNG24\n", rgb15);
154 case PNG_COLOR_TYPE_PALETTE:
156 png_get_PLTE(png_ptr, png_info_ptr, &palette, &palette_num);
157 if (png_get_tRNS(png_ptr, png_info_ptr, &trans, &num_trans,
158 &trans_values) && (num_trans > 0)) {
159 *tag_no = 36; // DefineBitsLossless2
161 *tag_no = 20; // DefineBitsLossless
164 case PNG_COLOR_TYPE_RGB:
170 *tag_no = 20; /* DefineBitsLossless */
172 case PNG_COLOR_TYPE_RGB_ALPHA:
174 *tag_no = 36; /* DefineBitsLossless2 */
175 if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS))
176 png_set_tRNS_to_alpha(png_ptr);
179 fprintf(stderr, "pngconv_png2lossless: color_type=%d not implemented yet.\n", color_type);
180 png_destroy_read_struct((png_structpp)&png_ptr,
181 (png_infopp)&png_info_ptr, NULL);
185 fprintf(stderr, "pngconv_png2lossless: bpp=%d not implemented yet. accept only bpp <= 8\n", bpp);
186 png_destroy_read_struct((png_structpp)&png_ptr,
187 (png_infopp)&png_info_ptr, NULL);
191 png_image_data = (png_bytepp) malloc(png_height * sizeof(png_bytep));
192 for (y=0 ; y < png_height ; y++) {
193 png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr));
195 png_read_image(png_ptr, png_image_data);
199 if (color_type == PNG_COLOR_TYPE_PALETTE) {
201 unsigned char *indices_data;
202 *colormap_count = palette_num;
203 if (num_trans == 0) {
204 swf_rgb_t *result_colormap = malloc(sizeof(swf_rgb_t) * palette_num); // Lossless
205 for (i=0 ; i < palette_num ; i++) {
206 result_colormap[i].red = palette[i].red;
207 result_colormap[i].green = palette[i].green;
208 result_colormap[i].blue = palette[i].blue;
210 *colormap = result_colormap;
212 swf_rgba_t *result_colormap = malloc(sizeof(swf_rgba_t) * palette_num); // Lossless2
213 for (i=0 ; i < palette_num ; i++) {
215 int alpha_value = trans[i];
216 result_colormap[i].red = palette[i].red * alpha_value / 0xff;
217 result_colormap[i].green = palette[i].green * alpha_value / 0xff;
218 result_colormap[i].blue = palette[i].blue * alpha_value / 0xff;
219 result_colormap[i].alpha = alpha_value;
221 result_colormap[i].red = palette[i].red;
222 result_colormap[i].green = palette[i].green;
223 result_colormap[i].blue = palette[i].blue;
224 result_colormap[i].alpha = 0xff; // opaque
227 *colormap = result_colormap;
229 indices_data = malloc(((png_width+ 3) & -4) * png_height);
231 for (y=0 ; y < png_height ; y++) {
232 bitstream_t *bs = bitstream_open();
237 // free png image datas
240 bitstream_input(bs, png_image_data[y], png_width);
241 for (x=0 ; x < png_width ; x++) {
242 indices_data[i] = bitstream_getbits(bs, bpp);
245 while (i % 4) { i++; } // 4byte alignment
248 image_data = indices_data;
249 } else if (color_type == PNG_COLOR_TYPE_RGB) {
250 swf_xrgb_t *xrgb_list;
251 xrgb_list = malloc(sizeof(swf_xrgb_t) * png_width * png_height);
252 for (y=0 ; y < png_height ; y++) {
253 for (x=0 ; x < png_width ; x++) {
254 xrgb_list[x+y*png_width].red = png_image_data[y][3*x + 0];
255 xrgb_list[x+y*png_width].green = png_image_data[y][3*x + 1];
256 xrgb_list[x+y*png_width].blue = png_image_data[y][3*x + 2];
259 image_data = xrgb_list;
260 } else { // PNG_COLOR_TYPE_RGB_ALPHA
261 swf_argb_t *argb_list;
262 argb_list = malloc(sizeof(swf_argb_t) * png_width * png_height);
263 for (y=0 ; y < png_height ; y++) {
264 for (x=0 ; x < png_width ; x++) {
265 int alpha_value = png_image_data[y][4*x + 3];
266 argb_list[x+y*png_width].red = png_image_data[y][4*x + 0] * alpha_value / 0xff;
267 argb_list[x+y*png_width].green = png_image_data[y][4*x + 1] * alpha_value / 0xff;
268 argb_list[x+y*png_width].blue = png_image_data[y][4*x + 2] * alpha_value / 0xff;
269 argb_list[x+y*png_width].alpha = alpha_value;
272 image_data = argb_list;
274 for (y=0 ; y < png_height ; y++) {
275 free(png_image_data[y]);
277 free(png_image_data);
281 png_destroy_read_struct((png_structpp) &png_ptr,
282 (png_infopp) &png_info_ptr, NULL);
287 pngconv_lossless2png(void *image_data,
288 unsigned short width, unsigned short height,
290 unsigned short index_data_count,
291 int tag_no, int format,
292 unsigned long *length) {
293 volatile png_structp png_ptr = NULL;
294 volatile png_infop png_info_ptr = NULL;
295 volatile my_png_buffer png_buff;
296 png_uint_32 png_width = 0, png_height = 0;
298 volatile png_bytepp png_image_data = NULL;
300 volatile png_colorp png_palette = NULL;
301 if (image_data == NULL) {
302 fprintf(stderr, "pngconv_lossless2png: image_data == NULL\n");
305 if ((format != 3) && (format != 5)) {
306 fprintf(stderr, "jpegconv_lossless2png: format=%d not implemented yes.\n", format);
309 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL);
311 fprintf(stderr, "jpegconv_lossless2png: can't create write_struct\n");
314 if (setjmp(png_jmpbuf(png_ptr))) {
315 fprintf(stderr, "pngconv_lossless2png: libpng error jump occured\n");
317 if (png_image_data) {
318 for (y=0 ; y < png_height ; y++) {
319 free(png_image_data[y]);
321 free(png_image_data);
324 png_destroy_write_struct((png_structpp) &png_ptr,
325 (png_infopp) &png_info_ptr);
328 png_info_ptr = png_create_info_struct(png_ptr);
329 if (! png_info_ptr) {
330 fprintf(stderr, "jpegconv_lossless2png: can't create info_struct\n");
331 png_destroy_write_struct((png_structpp) &png_ptr, NULL);
339 color_type = PNG_COLOR_TYPE_PALETTE;
340 } else if (tag_no == 20) { /* DefineBitsLossless */
341 color_type = PNG_COLOR_TYPE_RGB;
342 } else if (tag_no == 36) { /* DefineBitsLossless2 */
343 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
345 fprintf(stderr, "jpegconv_lossless2png: format!=3 and tag_no=%d not implemented.\n",
347 png_destroy_write_struct((png_structpp) &png_ptr,
348 (png_infopp) &png_info_ptr);
351 png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
352 png_set_IHDR(png_ptr, png_info_ptr,
353 png_width, png_height, bpp, color_type,
354 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
355 PNG_FILTER_TYPE_DEFAULT);
358 if (index_data_count == 0) {
359 fprintf(stderr, "jpegconv_lossless2png: index_data_count == 0 at line(%d)\n", __LINE__);
360 png_destroy_write_struct((png_structpp) &png_ptr,
361 (png_infopp) &png_info_ptr);
364 png_palette = (png_colorp) malloc(sizeof(png_color)*index_data_count);
365 png_set_packing(png_ptr);
367 swf_rgb_t *rgb_list = index_data;
368 for (i=0 ; i < index_data_count ; i++) {
369 png_palette[i].red = rgb_list[i].red;
370 png_palette[i].green = rgb_list[i].green;
371 png_palette[i].blue = rgb_list[i].blue;
374 swf_rgba_t *rgba_list = index_data;
375 png_bytep trans = NULL;
377 png_color_16p trans_values = NULL;
378 for (i=0 ; i < index_data_count ; i++) {
379 png_palette[i].red = rgba_list[i].red;
380 png_palette[i].green = rgba_list[i].green;
381 png_palette[i].blue = rgba_list[i].blue;
383 // scanning to end of transparent pixel
384 for (i = index_data_count - 1 ; 0 <= i ; i--) {
385 if (rgba_list[i].alpha < 254) { // 254 XXX
391 trans = malloc(num_trans);
392 for (i = 0 ; i < num_trans ; i++) {
393 trans[i] = rgba_list[i].alpha;
395 png_set_tRNS(png_ptr, png_info_ptr, trans, num_trans,
401 png_set_PLTE( png_ptr, png_info_ptr, png_palette, index_data_count);
404 png_image_data = (png_bytepp) malloc(png_height * sizeof(png_bytep));
405 if (color_type == PNG_COLOR_TYPE_PALETTE) {
406 for (y=0 ; y < png_height ; y++) {
407 png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr));
408 for (x=0 ; x < png_width ; x++) {
409 unsigned char *data = image_data;
410 png_image_data[y][x] = data[x + y*((png_width +3) & -4)];
414 } else if (color_type == PNG_COLOR_TYPE_RGB) {
415 swf_xrgb_t *xrgb_list = image_data;
416 for (y=0 ; y < png_height ; y++) {
417 png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr));
418 for (x=0 ; x < png_width ; x++) {
419 png_image_data[y][3*x] = xrgb_list[x+y*png_width].red;
420 png_image_data[y][3*x+1] = xrgb_list[x+y*png_width].green;
421 png_image_data[y][3*x+2] = xrgb_list[x+y*png_width].blue;
425 swf_argb_t *argb_list = image_data;
426 for (y=0 ; y < png_height ; y++) {
427 png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr));
428 for (x=0 ; x < png_width ; x++) {
429 png_image_data[y][4*x] = argb_list[x+y*png_width].red;
430 png_image_data[y][4*x+1] = argb_list[x+y*png_width].green;
431 png_image_data[y][4*x+2] = argb_list[x+y*png_width].blue;
432 png_image_data[y][4*x+3] = argb_list[x+y*png_width].alpha;
437 png_buff.data = NULL;
438 png_buff.data_len = 0;
439 png_buff.data_offset = 0;
440 png_data_write((png_structp) png_ptr, (my_png_buffer*) &png_buff);
442 png_write_info(png_ptr, png_info_ptr);
443 png_write_image(png_ptr, png_image_data);
444 png_write_end(png_ptr, png_info_ptr);
446 for (y=0 ; y < png_height ; y++) {
447 free(png_image_data[y]);
449 free(png_image_data);
450 png_destroy_write_struct((png_structpp) &png_ptr,
451 (png_infopp) &png_info_ptr);
452 *length = png_buff.data_offset;
453 return png_buff.data;
456 #endif /* HAVE_PNG */