diff options
author | Fabrice Bellard <fabrice@bellard.org> | 2003-02-09 16:22:06 +0000 |
---|---|---|
committer | Fabrice Bellard <fabrice@bellard.org> | 2003-02-09 16:22:06 +0000 |
commit | 3ce27f13b9a6a0435cfa5c0b1c50419886e08eb1 (patch) | |
tree | 8d20ff7affed28f33e38ff8baaf77e3a5a6f2fa5 | |
parent | 7e6d70d0b14f1dccd6204f8d23a6159ffc49b8e0 (diff) | |
download | ffmpeg-3ce27f13b9a6a0435cfa5c0b1c50419886e08eb1.tar.gz |
added 8 bit palette support
Originally committed as revision 1561 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavformat/png.c | 87 |
1 files changed, 83 insertions, 4 deletions
diff --git a/libavformat/png.c b/libavformat/png.c index a41c991458..e4facf80fa 100644 --- a/libavformat/png.c +++ b/libavformat/png.c @@ -41,6 +41,7 @@ #define PNG_IHDR 0x0001 #define PNG_IDAT 0x0002 #define PNG_ALLIMAGE 0x0004 +#define PNG_PLTE 0x0008 #define IOBUF_SIZE 4096 @@ -58,6 +59,7 @@ typedef struct PNGDecodeState { uint8_t *image_buf; int image_linesize; + uint32_t palette[256]; uint8_t *crow_buf; uint8_t *empty_row; int crow_size; /* compressed row size (include filter type) */ @@ -66,7 +68,7 @@ typedef struct PNGDecodeState { z_stream zstream; } PNGDecodeState; -const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; +static const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; static int png_probe(AVProbeData *pd) { @@ -77,12 +79,12 @@ static int png_probe(AVProbeData *pd) return 0; } -void *png_zalloc(void *opaque, unsigned int items, unsigned int size) +static void *png_zalloc(void *opaque, unsigned int items, unsigned int size) { return av_malloc(items * size); } -void png_zfree(void *opaque, void *ptr) +static void png_zfree(void *opaque, void *ptr) { av_free(ptr); } @@ -287,6 +289,9 @@ static int png_read(ByteIOContext *f, s->color_type == PNG_COLOR_TYPE_GRAY) { info->pix_fmt = PIX_FMT_MONOBLACK; s->row_size = (s->width + 7) >> 3; + } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) { + info->pix_fmt = PIX_FMT_PAL8; + s->row_size = s->width;; } else { goto fail; } @@ -306,6 +311,9 @@ static int png_read(ByteIOContext *f, #endif s->image_buf = info->pict.data[0]; s->image_linesize = info->pict.linesize[0]; + /* copy the palette if needed */ + if (s->color_type == PNG_COLOR_TYPE_PALETTE) + memcpy(info->pict.data[1], s->palette, 256 * sizeof(uint32_t)); /* empty row is used if differencing to the first row */ s->empty_row = av_mallocz(s->row_size); if (!s->empty_row) @@ -323,6 +331,43 @@ static int png_read(ByteIOContext *f, /* skip crc */ crc = get_be32(f); break; + case MKTAG('P', 'L', 'T', 'E'): + { + int n, i, r, g, b; + + if ((length % 3) != 0 || length > 256 * 3) + goto skip_tag; + /* read the palette */ + n = length / 3; + for(i=0;i<n;i++) { + r = get_byte(f); + g = get_byte(f); + b = get_byte(f); + s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b; + } + for(;i<256;i++) { + s->palette[i] = (0xff << 24); + } + s->state |= PNG_PLTE; + crc = get_be32(f); + } + break; + case MKTAG('t', 'R', 'N', 'S'): + { + int v, i; + + /* read the transparency. XXX: Only palette mode supported */ + if (s->color_type != PNG_COLOR_TYPE_PALETTE || + length > 256 || + !(s->state & PNG_PLTE)) + goto skip_tag; + for(i=0;i<length;i++) { + v = get_byte(f); + s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24); + } + crc = get_be32(f); + } + break; case MKTAG('I', 'E', 'N', 'D'): if (!(s->state & PNG_ALLIMAGE)) goto fail; @@ -330,6 +375,7 @@ static int png_read(ByteIOContext *f, goto exit_loop; default: /* skip tag */ + skip_tag: url_fskip(f, length + 4); break; } @@ -399,6 +445,11 @@ static int png_write(ByteIOContext *f, AVImageInfo *info) color_type = PNG_COLOR_TYPE_GRAY; row_size = (info->width + 7) >> 3; break; + case PIX_FMT_PAL8: + bit_depth = 8; + color_type = PNG_COLOR_TYPE_PALETTE; + row_size = info->width; + break; default: return -1; } @@ -426,6 +477,34 @@ static int png_write(ByteIOContext *f, AVImageInfo *info) png_write_chunk(f, MKTAG('I', 'H', 'D', 'R'), buf, 13); + /* put the palette if needed */ + if (color_type == PNG_COLOR_TYPE_PALETTE) { + int has_alpha, alpha, i; + unsigned int v; + uint32_t *palette; + uint8_t *alpha_ptr; + + palette = (uint32_t *)info->pict.data[1]; + ptr = buf; + alpha_ptr = buf + 256 * 3; + has_alpha = 0; + for(i = 0; i < 256; i++) { + v = palette[i]; + alpha = v >> 24; + if (alpha != 0xff) + has_alpha = 1; + *alpha_ptr++ = alpha; + ptr[0] = v >> 16; + ptr[1] = v >> 8; + ptr[2] = v; + ptr += 3; + } + png_write_chunk(f, MKTAG('P', 'L', 'T', 'E'), buf, 256 * 3); + if (has_alpha) { + png_write_chunk(f, MKTAG('t', 'R', 'N', 'S'), buf + 256 * 3, 256); + } + } + /* now put each row */ zstream.avail_out = IOBUF_SIZE; zstream.next_out = buf; @@ -481,6 +560,6 @@ AVImageFormat png_image_format = { "png", png_probe, png_read, - (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_MONOBLACK), + (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_MONOBLACK) | (1 << PIX_FMT_PAL8), png_write, }; |