2 +----------------------------------------------------------------------+
3 | Author: yoya@awm.jp |
4 +----------------------------------------------------------------------+
9 #include <string.h> /* strndup */
11 #include "bitstream.h"
12 #include "swf_define.h"
13 #include "swf_tag_lossless.h"
14 #include "swf_object.h"
18 swf_tag_detail_handler_t lossless_detail_handler;
20 swf_tag_detail_handler_t *swf_tag_lossless_detail_handler(void) {
21 lossless_detail_handler.create = swf_tag_lossless_create_detail;
22 lossless_detail_handler.input = swf_tag_lossless_input_detail;
23 lossless_detail_handler.get_cid = swf_tag_lossless_get_cid_detail;
24 lossless_detail_handler.replace_cid = swf_tag_lossless_replace_cid_detail;
25 lossless_detail_handler.output = swf_tag_lossless_output_detail;
26 lossless_detail_handler.print = swf_tag_lossless_print_detail;
27 lossless_detail_handler.destroy = swf_tag_lossless_destroy_detail;
28 return &lossless_detail_handler;
32 swf_tag_lossless_create_detail(void) {
33 swf_tag_lossless_detail_t *swf_tag_lossless;
34 swf_tag_lossless = calloc(sizeof(*swf_tag_lossless), 1);
35 if (swf_tag_lossless == NULL) {
36 fprintf(stderr, "swf_tag_lossless_create_detail: can't calloc swf_tag_lossless\n");
39 swf_tag_lossless->image_id = 0;
40 swf_tag_lossless->format = 0;
41 swf_tag_lossless->width = 0;
42 swf_tag_lossless->height = 0;
43 swf_tag_lossless->colormap_count = 0;
44 swf_tag_lossless->colormap = NULL;
45 swf_tag_lossless->colormap2 = NULL;
46 swf_tag_lossless->indices = NULL;
47 swf_tag_lossless->bitmap = NULL;
48 swf_tag_lossless->bitmap2 = NULL;
49 return swf_tag_lossless;
53 swf_tag_lossless_input_detail(swf_tag_t *tag,
54 struct swf_object_ *swf) {
55 swf_tag_lossless_detail_t *swf_tag_lossless = NULL;
56 unsigned char *data = NULL;
58 bitstream_t *bs = NULL, *bs2 = NULL;
60 unsigned char *tmp_buff = NULL, *old_buff_ref = NULL;
61 unsigned long origsize, old_size, offset;
65 fprintf(stderr, "swf_tag_lossless_input_detail: tag == NULL\n");
68 if (tag->detail == NULL) {
69 fprintf(stderr, "swf_tag_lossless_input_detail: tag->detail== NULL\n");
72 swf_tag_lossless = tag->detail;
76 bs = bitstream_open();
77 bitstream_input(bs, data, length);
78 swf_tag_lossless->image_id = bitstream_getbytesLE(bs, 2);
79 swf_tag_lossless->format = bitstream_getbyte(bs);
80 swf_tag_lossless->width = bitstream_getbytesLE(bs, 2);
81 swf_tag_lossless->height = bitstream_getbytesLE(bs, 2);
82 if (swf_tag_lossless->format == 3) {
83 unsigned long indices_len;
85 swf_tag_lossless->colormap_count = bitstream_getbyte(bs) + 1;
86 indices_len = ((swf_tag_lossless->width + 3) & -4) * swf_tag_lossless->height;
87 if (tag->code == 20) { // Lossless => rgb (3 bytes)
89 } else { // Lossless2 => rgba (4 bytes)
92 origsize = bytes_per_color * swf_tag_lossless->colormap_count + indices_len;
93 tmp_buff = malloc(origsize);
94 offset = bitstream_getbytepos(bs);
95 old_buff_ref = bitstream_buffer(bs, offset);
96 old_size = bitstream_length(bs) - offset;
97 result = uncompress(tmp_buff, &origsize, old_buff_ref, old_size);
99 if (result == Z_MEM_ERROR) {
100 fprintf(stderr, "swf_tag_lossless_input_detaill: uncompress: Z_MEM_ERROR: can't malloc at line(%d)\n", __LINE__);
101 } else if (result == Z_BUF_ERROR) {
102 fprintf(stderr, "swf_tag_lossless_input_detail: uncompress: Z_BUF_ERROR: not enough buff size at line(%d)\n", __LINE__);
103 } else if (result == Z_DATA_ERROR) {
104 fprintf(stderr, "swf_tag_lossless_input_detail: uncompress: Z_DATA_ERROR: corrupted or imcomplete data at line(%d)\n", __LINE__);
106 fprintf(stderr, "swf_tag_lossless_input_detail: uncompress: failed byunknown reason (%d) at line(%d)\n", result, __LINE__);
112 if (indices_len != origsize - bytes_per_color * swf_tag_lossless->colormap_count) {
113 fprintf(stderr, "swf_tag_lossless_input_detail: indices_len(%lu) != origsize(%lu) - %d * swf_tag_lossless->colormap_count(%d) at line(%d)\n",
114 indices_len, origsize, bytes_per_color,
115 swf_tag_lossless->colormap_count, __LINE__);
120 bs2 = bitstream_open();
121 bitstream_input(bs2, tmp_buff, origsize);
122 if (tag->code == 20) { // Lossless
123 swf_tag_lossless->colormap = malloc(sizeof(swf_rgb_t) * swf_tag_lossless->colormap_count);
124 for (i=0 ; i < swf_tag_lossless->colormap_count ; i++) {
125 swf_rgb_t *rgb = swf_tag_lossless->colormap + i;
126 swf_rgb_parse(bs2, rgb);
128 } else { // tag == 36 (Lossless2)
129 swf_tag_lossless->colormap2 = malloc(sizeof(swf_rgba_t) * swf_tag_lossless->colormap_count);
130 for (i=0 ; i < swf_tag_lossless->colormap_count ; i++) {
131 swf_rgba_t *rgba = swf_tag_lossless->colormap2 + i;
132 swf_rgba_parse(bs2, rgba);
135 swf_tag_lossless->indices = malloc(indices_len);
136 bitstream_getstring(bs2, swf_tag_lossless->indices, indices_len);
137 bitstream_close(bs2);
139 } else { // format != 3
140 unsigned long bitmap_count;
141 bitmap_count = swf_tag_lossless->width * swf_tag_lossless->height;
142 origsize = 4 * bitmap_count; // xrgb or argb (4 bytes)
143 tmp_buff = malloc(origsize);
144 offset = bitstream_getbytepos(bs);
145 old_buff_ref = bitstream_buffer(bs, offset);
146 old_size = bitstream_length(bs) - offset;
147 result = uncompress(tmp_buff, &origsize, old_buff_ref, old_size);
148 if (result != Z_OK) {
149 if (result == Z_MEM_ERROR) {
150 fprintf(stderr, "swf_tag_lossless_input_detail: uncompress: Z_MEM_ERROR: can't malloc (origsize=%lu, old_size=%lu) at line(%d)\n",
151 origsize, old_size, __LINE__);
152 } else if (result == Z_BUF_ERROR) {
153 fprintf(stderr, "swf_tag_lossless_input_detail: uncompress: Z_BUF_ERROR: not enough buff size(origsize=%lu, old_size=%lu) at line(%d)\n",
154 origsize, old_size, __LINE__);
155 } else if (result == Z_DATA_ERROR) {
156 fprintf(stderr, "swf_tag_lossless_input_detail: uncompress: Z_DATA_ERROR: corrupted or imcomplete data at line(%d)\n", __LINE__);
158 fprintf(stderr, "swf_tag_lossless_input_detail: uncompress: failed byunknown reason (%d) at line(%d)\n", result, __LINE__);
164 bs2 = bitstream_open();
165 bitstream_input(bs2, tmp_buff, origsize);
166 if (tag->code == 20) { // Lossless
167 swf_tag_lossless->bitmap = malloc(bitmap_count * sizeof(swf_xrgb_t));
168 for (i=0 ; i < bitmap_count ; i++) {
169 swf_xrgb_t *xrgb = swf_tag_lossless->bitmap + i;
170 swf_xrgb_parse(bs2, xrgb);
172 } else { // tag == 36 (Lossless2)
173 swf_tag_lossless->bitmap2 = malloc(bitmap_count * sizeof(swf_argb_t));
174 for (i=0 ; i < bitmap_count ; i++) {
175 swf_argb_t *argb = swf_tag_lossless->bitmap2 + i;
176 swf_argb_parse(bs2, argb);
179 bitstream_close(bs2);
188 swf_tag_lossless_get_cid_detail(swf_tag_t *tag) {
189 unsigned char *data = NULL;
191 fprintf(stderr, "swf_tag_lossless_get_cid_detail: tag == NULL\n");
196 swf_tag_lossless_detail_t *swf_tag_lossless = (swf_tag_lossless_detail_t *) tag->detail;
197 return swf_tag_lossless->image_id;
200 fprintf(stderr, "swf_tag_lossless_get_cid_detail: data==NULL at line(%d)\n", __LINE__);
203 return GetUShortLE(data); // image_id;
207 swf_tag_lossless_replace_cid_detail(swf_tag_t *tag, int id) {
208 unsigned char *data = NULL;
210 fprintf(stderr, "swf_tag_lossless_replace_cid_detail: tag == NULL\n");
215 swf_tag_lossless_detail_t *swf_tag_lossless = (swf_tag_lossless_detail_t *) tag->detail;
216 swf_tag_lossless->image_id = id;
219 PutUShortLE(data, id);
221 return 0; // always 0
225 swf_tag_lossless_output_detail(swf_tag_t *tag, unsigned long *length,
226 struct swf_object_ *swf) {
227 swf_tag_lossless_detail_t *swf_tag_lossless = (swf_tag_lossless_detail_t *) tag->detail;
228 bitstream_t *bs = NULL, *bs2 = NULL;
229 unsigned char *data = NULL;
231 unsigned char *tmp_buff = NULL, *old_buff_ref = NULL;
232 unsigned long compsize, old_size;
235 fprintf(stderr, "swf_tag_lossless_output_detail: tag == NULL\n");
239 fprintf(stderr, "swf_tag_lossless_output_detail: swf == NULL\n");
242 if (length == NULL) {
243 fprintf(stderr, "swf_tag_lossless_output_detail: length == NULL\n");
248 bs = bitstream_open();
249 bitstream_putbytesLE(bs, swf_tag_lossless->image_id, 2);
250 bitstream_putbyte(bs, swf_tag_lossless->format);
251 bitstream_putbytesLE(bs, swf_tag_lossless->width, 2);
252 bitstream_putbytesLE(bs, swf_tag_lossless->height, 2);
253 if (swf_tag_lossless->format == 3) {
254 unsigned long indices_len;
255 bitstream_putbyte(bs, swf_tag_lossless->colormap_count - 1); /* XXX */
256 bs2 = bitstream_open();
257 if (tag->code == 20) { // Lossless
258 for (i=0 ; i < swf_tag_lossless->colormap_count ; i++) {
259 swf_rgb_t *rgb = swf_tag_lossless->colormap + i;
260 swf_rgb_build(bs2, rgb);
262 } else { // tag == 36 (Lossless2)
263 for (i=0 ; i < swf_tag_lossless->colormap_count ; i++) {
264 swf_rgba_t *rgba = swf_tag_lossless->colormap2 + i;
265 swf_rgba_build(bs2, rgba);
268 indices_len = ((swf_tag_lossless->width + 3) & -4) * swf_tag_lossless->height;
269 bitstream_putstring(bs2, swf_tag_lossless->indices,
271 old_buff_ref = bitstream_buffer(bs2, 0);
272 old_size = bitstream_length(bs2);
273 compsize = old_size * 1.001 + 12; // increasing, rarely situation
274 tmp_buff = malloc(compsize);
275 result = compress2(tmp_buff, &compsize, old_buff_ref, old_size, swf->compress_level);
276 if (result != Z_OK) {
277 if (result == Z_MEM_ERROR) {
278 fprintf(stderr, "swf_tag_lossless_output_detail: compress Z_MEM_ERROR: can't malloc\n");
279 } else if (result == Z_BUF_ERROR) {
280 fprintf(stderr, "swf_tag_lossless_output_detail: compress Z_BUF_ERROR: not enough buff size\n");
282 fprintf(stderr, "swf_tag_lossless_output_detail: compress failed by unknown reason\n");
284 bitstream_close(bs2);
287 return NULL; // FAILURE
289 bitstream_putstring(bs, tmp_buff, compsize);
290 bitstream_close(bs2);
292 } else { // format == 4 or format == 5
293 unsigned long bitmap_size;
294 bs2 = bitstream_open();
295 if (tag->code == 20) { // Lossless
296 bitmap_size = swf_tag_lossless->width * swf_tag_lossless->height;
297 if (swf_tag_lossless->format == 4) {
299 int width_padding = (swf_tag_lossless->width%2)?1:0;
301 for (y = 0 ; y < swf_tag_lossless->height ; y++) {
302 for (x = 0 ; x < swf_tag_lossless->width ; x++) {
303 swf_xrgb_t *xrgb = swf_tag_lossless->bitmap + i;
304 bitstream_putbit(bs2, 0);
305 bitstream_putbits(bs2, xrgb->red >> 3, 5);
306 bitstream_putbits(bs2, xrgb->green >> 3, 5);
307 bitstream_putbits(bs2, xrgb->blue >> 3, 5);
311 bitstream_putstring(bs2, (unsigned char *)"\0\0", 2);
315 for (i=0 ; i < bitmap_size ; i++) {
316 swf_xrgb_t *xrgb = swf_tag_lossless->bitmap + i;
317 swf_xrgb_build(bs2, xrgb);
320 } else { // tag == 36 (Lossless2)
321 bitmap_size = swf_tag_lossless->width * swf_tag_lossless->height;
322 for (i=0 ; i < bitmap_size ; i++) {
323 swf_argb_t *argb = swf_tag_lossless->bitmap2 + i;
324 swf_argb_build(bs2, argb);
327 old_buff_ref = bitstream_buffer(bs2, 0);
328 old_size = bitstream_length(bs2);
329 compsize = old_size * 1.001 + 12; // increasing, rarely situation
330 tmp_buff = malloc(compsize);
331 result = compress2(tmp_buff, &compsize, old_buff_ref, old_size, swf->compress_level);
332 if (result != Z_OK) {
333 if (result == Z_MEM_ERROR) {
334 fprintf(stderr, "swf_tag_lossless_output_detail: compress Z_MEM_ERROR: can't malloc\n");
335 } else if (result == Z_BUF_ERROR) {
336 fprintf(stderr, "swf_tag_lossless_output_detail: compress Z_BUF_ERROR: not enough buff size\n");
338 fprintf(stderr, "swf_tag_lossless_output_detail: compress failed by unknown reason\n");
340 bitstream_close(bs2);
343 return NULL; // FAILURE
345 bitstream_putstring(bs, tmp_buff, compsize);
346 bitstream_close(bs2);
349 data = bitstream_steal(bs, length);
355 swf_tag_lossless_print_detail(swf_tag_t *tag,
356 struct swf_object_ *swf, int indent_depth) {
357 swf_tag_lossless_detail_t *swf_tag_lossless = NULL;
360 fprintf(stderr, "swf_tag_lossless_print_detail: tag == NULL\n");
363 if (tag->detail == NULL) {
364 fprintf(stderr, "swf_tag_lossless_print_detail: tag->detail == NULL\n");
367 swf_tag_lossless = (swf_tag_lossless_detail_t *) tag->detail;
368 print_indent(indent_depth);
369 printf("image_id=%d format=%d width=%u height=%u\n",
370 swf_tag_lossless->image_id, swf_tag_lossless->format,
371 swf_tag_lossless->width, swf_tag_lossless->height);
372 if (swf_tag_lossless->colormap ||
373 swf_tag_lossless->colormap2) {
374 print_indent(indent_depth);
375 printf("colormap_count=%d",
376 swf_tag_lossless->colormap_count);
377 if (swf_tag_lossless->colormap) {
378 printf(" rgb colormap exists");
380 printf(" rgba colormap exists");
382 if (swf_tag_lossless->indices) {
383 printf(" indices exists");
387 if (swf_tag_lossless->bitmap) {
388 print_indent(indent_depth);
389 printf("xrgb bitmap exists\n");
391 if (swf_tag_lossless->bitmap2) {
392 print_indent(indent_depth);
393 printf("argb bitmap exists\n");
398 swf_tag_lossless_destroy_detail(swf_tag_t *tag) {
399 swf_tag_lossless_detail_t *swf_tag_lossless;
401 fprintf(stderr, "swf_tag_lossless_destroy_detail: tag == NULL\n");
404 swf_tag_lossless = (swf_tag_lossless_detail_t *) tag->detail;
405 if (swf_tag_lossless) {
406 free(swf_tag_lossless->colormap);
407 free(swf_tag_lossless->colormap2);
408 free(swf_tag_lossless->indices);
409 free(swf_tag_lossless->bitmap);
410 free(swf_tag_lossless->bitmap2);
411 swf_tag_lossless->colormap = NULL;
412 swf_tag_lossless->colormap2 = NULL;
413 swf_tag_lossless->indices = NULL;
414 swf_tag_lossless->bitmap = NULL;
415 swf_tag_lossless->bitmap2 = NULL;
416 free(swf_tag_lossless);
424 unsigned char *swf_tag_lossless_get_png_data(void *detail,
425 unsigned long *length,
428 swf_tag_lossless_detail_t *swf_tag_lossless = (swf_tag_lossless_detail_t *) detail;
429 unsigned char *data = NULL;
430 void *index_data = NULL;
431 void *image_data = NULL;
433 if (detail == NULL) {
434 fprintf(stderr, "swf_tag_lossless_get_lossless_data: detail == NULL at line(%d)\n", __LINE__);
437 if (length == NULL) {
438 fprintf(stderr, "swf_tag_lossless_get_lossless_data: length == NULL at line(%d)\n", __LINE__);
441 if (swf_tag_lossless->image_id != image_id) {
444 if ((swf_tag_lossless->format != 3) && (swf_tag_lossless->format != 5)) {
445 fprintf(stderr, "swf_tag_lossless_get_lossless_data: format=%d not implemented yet\n",
446 swf_tag_lossless->format);
449 if (tag->code == 20) {
450 if (swf_tag_lossless->format == 3) {
451 index_data = (void *) swf_tag_lossless->colormap;
452 image_data = (void *) swf_tag_lossless->indices;
454 image_data = (void *) swf_tag_lossless->bitmap;
457 if (swf_tag_lossless->format == 3) {
458 index_data = (void *) swf_tag_lossless->colormap2;
459 image_data = (void *) swf_tag_lossless->indices;
461 image_data = (void *) swf_tag_lossless->bitmap2;
464 if (image_data == NULL) {
465 fprintf(stderr, "swf_tag_lossless_get_lossless_data: image_data == NULL at line(%d)\n", __LINE__);
468 data = pngconv_lossless2png(image_data,
469 swf_tag_lossless->width,
470 swf_tag_lossless->height,
472 swf_tag_lossless->colormap_count,
473 tag->code, swf_tag_lossless->format,
479 swf_tag_lossless_replace_png_data(void *detail, int image_id,
480 unsigned char *png_data,
481 unsigned long png_data_len,
482 int rgb15, swf_tag_t *tag) {
484 unsigned short width, height;
485 unsigned char *result_data = NULL;
486 void *colormap = NULL;
487 int colormap_count = 0;
488 swf_tag_lossless_detail_t *swf_tag_lossless = (swf_tag_lossless_detail_t *) detail;
489 if (detail == NULL) {
490 fprintf(stderr, "swf_tag_lossess_replace_png_data: detail == NULL at line(%d)\n", __LINE__);
493 if (png_data == NULL) {
494 fprintf(stderr, "swf_tag_lossess_replace_png_data: png_data == NULL at line(%d)\n", __LINE__);
497 swf_tag_lossless->image_id = image_id;
498 result_data = pngconv_png2lossless(png_data, png_data_len,
501 &colormap, &colormap_count, rgb15);
503 if (result_data == NULL) {
504 fprintf(stderr, "swf_tag_lossess_replace_png_data: pngconv_png2lossless failed at line(%d)\n", __LINE__);
508 swf_tag_lossless->format = format;
509 swf_tag_lossless->width = width;
510 swf_tag_lossless->height = height;
512 free(swf_tag_lossless->colormap);
513 free(swf_tag_lossless->colormap2);
514 free(swf_tag_lossless->indices);
515 free(swf_tag_lossless->bitmap);
516 free(swf_tag_lossless->bitmap2);
517 swf_tag_lossless->colormap = NULL;
518 swf_tag_lossless->colormap2 = NULL;
519 swf_tag_lossless->indices = NULL;
520 swf_tag_lossless->bitmap = NULL;
521 swf_tag_lossless->bitmap2 = NULL;
523 swf_tag_lossless->colormap = (swf_rgb_t*) colormap;
524 } else if (tag_no == 36) {
525 swf_tag_lossless->colormap2 = (swf_rgba_t*) colormap;
527 fprintf(stderr, "swf_tag_lossess_replace_png_data: internal error tag_no(%d) at line(%d).\n", tag_no, __LINE__);
530 swf_tag_lossless->colormap_count = colormap_count;
531 swf_tag_lossless->indices = (unsigned char *) result_data;
532 } else if ((format == 4) || (format == 5)) {
533 free(swf_tag_lossless->colormap);
534 free(swf_tag_lossless->colormap2);
535 free(swf_tag_lossless->indices);
536 free(swf_tag_lossless->bitmap);
537 free(swf_tag_lossless->bitmap2);
538 swf_tag_lossless->colormap = NULL;
539 swf_tag_lossless->colormap2 = NULL;
540 swf_tag_lossless->indices = NULL;
541 swf_tag_lossless->bitmap = NULL;
542 swf_tag_lossless->bitmap2 = NULL;
544 swf_tag_lossless->bitmap = (swf_xrgb_t*) result_data;
545 } else if (tag_no == 36) {
546 swf_tag_lossless->bitmap2 = (swf_argb_t*) result_data;
548 fprintf(stderr, "swf_tag_lossless_replace_png_data: internal error tag_no(%d) at line(%d).\n", tag_no, __LINE__);
552 fprintf(stderr, "swf_tag_lossless_replace_png_data: format(%d) not implemented yet. at line(%d)\n", format, __LINE__);
558 #endif /* HAVE_PNG */
563 swf_tag_lossless_replace_gif_data(void *detail, int image_id,
564 unsigned char *gif_data,
565 unsigned long gif_data_len, swf_tag_t *tag) {
567 unsigned short width, height;
568 unsigned char *result_data = NULL;
569 void *colormap = NULL;
570 int colormap_count = 0;
571 swf_tag_lossless_detail_t *swf_tag_lossless = (swf_tag_lossless_detail_t *) detail;
572 if (detail == NULL) {
573 fprintf(stderr, "swf_tag_lossless_replace_gif_data: detail == NULL at line(%d)\n", __LINE__);
576 if (gif_data == NULL) {
577 fprintf(stderr, "swf_tag_lossless_replace_gif_data: gif_data == NULL at line(%d)\n", __LINE__);
580 swf_tag_lossless->image_id = image_id;
581 result_data = gifconv_gif2lossless(gif_data, gif_data_len,
584 &colormap, &colormap_count);
586 if (result_data == NULL) {
587 fprintf(stderr, "swf_tag_lossless_replace_gif_data: gifconv_gif2lossless failed at line(%d)\n", __LINE__);
591 swf_tag_lossless->format = format;
592 swf_tag_lossless->width = width;
593 swf_tag_lossless->height = height;
595 free(swf_tag_lossless->colormap);
596 free(swf_tag_lossless->colormap2);
597 free(swf_tag_lossless->indices);
598 free(swf_tag_lossless->bitmap);
599 free(swf_tag_lossless->bitmap2);
600 swf_tag_lossless->colormap = NULL;
601 swf_tag_lossless->colormap2 = NULL;
602 swf_tag_lossless->indices = NULL;
603 swf_tag_lossless->bitmap = NULL;
604 swf_tag_lossless->bitmap2 = NULL;
606 swf_tag_lossless->colormap = (swf_rgb_t*) colormap;
607 } else if (tag_no == 36) {
608 swf_tag_lossless->colormap2 = (swf_rgba_t*) colormap;
610 fprintf(stderr, "swf_tag_lossless_replace_gif_data: internal error tag_no(%d) at line(%d).\n", tag_no, __LINE__);
613 swf_tag_lossless->colormap_count = colormap_count;
614 swf_tag_lossless->indices = (unsigned char *) result_data;
616 fprintf(stderr, "swf_tag_lossless_replace_gif_data: format(%d) not implemented yet. at line(%d)\n", format, __LINE__);
622 #endif /* HAVE_GIF */