Mercurial > libavformat.hg
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 }; |