aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2003-02-09 16:22:06 +0000
committerFabrice Bellard <fabrice@bellard.org>2003-02-09 16:22:06 +0000
commit3ce27f13b9a6a0435cfa5c0b1c50419886e08eb1 (patch)
tree8d20ff7affed28f33e38ff8baaf77e3a5a6f2fa5
parent7e6d70d0b14f1dccd6204f8d23a6159ffc49b8e0 (diff)
downloadffmpeg-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.c87
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,
};