comparison png.c @ 59:05be5bf0025e libavformat

added 8 bit palette support
author bellard
date Sun, 09 Feb 2003 16:22:06 +0000
parents bde449e6b743
children a803af1b10be
comparison
equal deleted inserted replaced
58:b1dd147434af 59:05be5bf0025e
39 #define PNG_FILTER_VALUE_PAETH 4 39 #define PNG_FILTER_VALUE_PAETH 4
40 40
41 #define PNG_IHDR 0x0001 41 #define PNG_IHDR 0x0001
42 #define PNG_IDAT 0x0002 42 #define PNG_IDAT 0x0002
43 #define PNG_ALLIMAGE 0x0004 43 #define PNG_ALLIMAGE 0x0004
44 #define PNG_PLTE 0x0008
44 45
45 #define IOBUF_SIZE 4096 46 #define IOBUF_SIZE 4096
46 47
47 typedef struct PNGDecodeState { 48 typedef struct PNGDecodeState {
48 int state; 49 int state;
56 int bits_per_pixel; 57 int bits_per_pixel;
57 int bpp; 58 int bpp;
58 59
59 uint8_t *image_buf; 60 uint8_t *image_buf;
60 int image_linesize; 61 int image_linesize;
62 uint32_t palette[256];
61 uint8_t *crow_buf; 63 uint8_t *crow_buf;
62 uint8_t *empty_row; 64 uint8_t *empty_row;
63 int crow_size; /* compressed row size (include filter type) */ 65 int crow_size; /* compressed row size (include filter type) */
64 int row_size; /* decompressed row size */ 66 int row_size; /* decompressed row size */
65 int y; 67 int y;
66 z_stream zstream; 68 z_stream zstream;
67 } PNGDecodeState; 69 } PNGDecodeState;
68 70
69 const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; 71 static const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
70 72
71 static int png_probe(AVProbeData *pd) 73 static int png_probe(AVProbeData *pd)
72 { 74 {
73 if (pd->buf_size >= 8 && 75 if (pd->buf_size >= 8 &&
74 memcmp(pd->buf, pngsig, 8) == 0) 76 memcmp(pd->buf, pngsig, 8) == 0)
75 return AVPROBE_SCORE_MAX; 77 return AVPROBE_SCORE_MAX;
76 else 78 else
77 return 0; 79 return 0;
78 } 80 }
79 81
80 void *png_zalloc(void *opaque, unsigned int items, unsigned int size) 82 static void *png_zalloc(void *opaque, unsigned int items, unsigned int size)
81 { 83 {
82 return av_malloc(items * size); 84 return av_malloc(items * size);
83 } 85 }
84 86
85 void png_zfree(void *opaque, void *ptr) 87 static void png_zfree(void *opaque, void *ptr)
86 { 88 {
87 av_free(ptr); 89 av_free(ptr);
88 } 90 }
89 91
90 /* XXX: optimize */ 92 /* XXX: optimize */
285 s->row_size = s->width; 287 s->row_size = s->width;
286 } else if (s->bit_depth == 1 && 288 } else if (s->bit_depth == 1 &&
287 s->color_type == PNG_COLOR_TYPE_GRAY) { 289 s->color_type == PNG_COLOR_TYPE_GRAY) {
288 info->pix_fmt = PIX_FMT_MONOBLACK; 290 info->pix_fmt = PIX_FMT_MONOBLACK;
289 s->row_size = (s->width + 7) >> 3; 291 s->row_size = (s->width + 7) >> 3;
292 } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
293 info->pix_fmt = PIX_FMT_PAL8;
294 s->row_size = s->width;;
290 } else { 295 } else {
291 goto fail; 296 goto fail;
292 } 297 }
293 /* compute the compressed row size */ 298 /* compute the compressed row size */
294 if (!s->interlace_type) { 299 if (!s->interlace_type) {
304 printf("row_size=%d crow_size =%d\n", 309 printf("row_size=%d crow_size =%d\n",
305 s->row_size, s->crow_size); 310 s->row_size, s->crow_size);
306 #endif 311 #endif
307 s->image_buf = info->pict.data[0]; 312 s->image_buf = info->pict.data[0];
308 s->image_linesize = info->pict.linesize[0]; 313 s->image_linesize = info->pict.linesize[0];
314 /* copy the palette if needed */
315 if (s->color_type == PNG_COLOR_TYPE_PALETTE)
316 memcpy(info->pict.data[1], s->palette, 256 * sizeof(uint32_t));
309 /* empty row is used if differencing to the first row */ 317 /* empty row is used if differencing to the first row */
310 s->empty_row = av_mallocz(s->row_size); 318 s->empty_row = av_mallocz(s->row_size);
311 if (!s->empty_row) 319 if (!s->empty_row)
312 goto fail; 320 goto fail;
313 /* compressed row */ 321 /* compressed row */
321 if (png_decode_idat(s, f, length) < 0) 329 if (png_decode_idat(s, f, length) < 0)
322 goto fail; 330 goto fail;
323 /* skip crc */ 331 /* skip crc */
324 crc = get_be32(f); 332 crc = get_be32(f);
325 break; 333 break;
334 case MKTAG('P', 'L', 'T', 'E'):
335 {
336 int n, i, r, g, b;
337
338 if ((length % 3) != 0 || length > 256 * 3)
339 goto skip_tag;
340 /* read the palette */
341 n = length / 3;
342 for(i=0;i<n;i++) {
343 r = get_byte(f);
344 g = get_byte(f);
345 b = get_byte(f);
346 s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
347 }
348 for(;i<256;i++) {
349 s->palette[i] = (0xff << 24);
350 }
351 s->state |= PNG_PLTE;
352 crc = get_be32(f);
353 }
354 break;
355 case MKTAG('t', 'R', 'N', 'S'):
356 {
357 int v, i;
358
359 /* read the transparency. XXX: Only palette mode supported */
360 if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
361 length > 256 ||
362 !(s->state & PNG_PLTE))
363 goto skip_tag;
364 for(i=0;i<length;i++) {
365 v = get_byte(f);
366 s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
367 }
368 crc = get_be32(f);
369 }
370 break;
326 case MKTAG('I', 'E', 'N', 'D'): 371 case MKTAG('I', 'E', 'N', 'D'):
327 if (!(s->state & PNG_ALLIMAGE)) 372 if (!(s->state & PNG_ALLIMAGE))
328 goto fail; 373 goto fail;
329 crc = get_be32(f); 374 crc = get_be32(f);
330 goto exit_loop; 375 goto exit_loop;
331 default: 376 default:
332 /* skip tag */ 377 /* skip tag */
378 skip_tag:
333 url_fskip(f, length + 4); 379 url_fskip(f, length + 4);
334 break; 380 break;
335 } 381 }
336 } 382 }
337 exit_loop: 383 exit_loop:
396 break; 442 break;
397 case PIX_FMT_MONOBLACK: 443 case PIX_FMT_MONOBLACK:
398 bit_depth = 1; 444 bit_depth = 1;
399 color_type = PNG_COLOR_TYPE_GRAY; 445 color_type = PNG_COLOR_TYPE_GRAY;
400 row_size = (info->width + 7) >> 3; 446 row_size = (info->width + 7) >> 3;
447 break;
448 case PIX_FMT_PAL8:
449 bit_depth = 8;
450 color_type = PNG_COLOR_TYPE_PALETTE;
451 row_size = info->width;
401 break; 452 break;
402 default: 453 default:
403 return -1; 454 return -1;
404 } 455 }
405 zstream.zalloc = png_zalloc; 456 zstream.zalloc = png_zalloc;
423 buf[10] = 0; /* compression type */ 474 buf[10] = 0; /* compression type */
424 buf[11] = 0; /* filter type */ 475 buf[11] = 0; /* filter type */
425 buf[12] = 0; /* interlace type */ 476 buf[12] = 0; /* interlace type */
426 477
427 png_write_chunk(f, MKTAG('I', 'H', 'D', 'R'), buf, 13); 478 png_write_chunk(f, MKTAG('I', 'H', 'D', 'R'), buf, 13);
479
480 /* put the palette if needed */
481 if (color_type == PNG_COLOR_TYPE_PALETTE) {
482 int has_alpha, alpha, i;
483 unsigned int v;
484 uint32_t *palette;
485 uint8_t *alpha_ptr;
486
487 palette = (uint32_t *)info->pict.data[1];
488 ptr = buf;
489 alpha_ptr = buf + 256 * 3;
490 has_alpha = 0;
491 for(i = 0; i < 256; i++) {
492 v = palette[i];
493 alpha = v >> 24;
494 if (alpha != 0xff)
495 has_alpha = 1;
496 *alpha_ptr++ = alpha;
497 ptr[0] = v >> 16;
498 ptr[1] = v >> 8;
499 ptr[2] = v;
500 ptr += 3;
501 }
502 png_write_chunk(f, MKTAG('P', 'L', 'T', 'E'), buf, 256 * 3);
503 if (has_alpha) {
504 png_write_chunk(f, MKTAG('t', 'R', 'N', 'S'), buf + 256 * 3, 256);
505 }
506 }
428 507
429 /* now put each row */ 508 /* now put each row */
430 zstream.avail_out = IOBUF_SIZE; 509 zstream.avail_out = IOBUF_SIZE;
431 zstream.next_out = buf; 510 zstream.next_out = buf;
432 for(y = 0;y < info->height; y++) { 511 for(y = 0;y < info->height; y++) {
479 AVImageFormat png_image_format = { 558 AVImageFormat png_image_format = {
480 "png", 559 "png",
481 "png", 560 "png",
482 png_probe, 561 png_probe,
483 png_read, 562 png_read,
484 (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_MONOBLACK), 563 (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_MONOBLACK) | (1 << PIX_FMT_PAL8),
485 png_write, 564 png_write,
486 }; 565 };