added 8 bit palette support

Originally committed as revision 1561 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Fabrice Bellard 2003-02-09 16:22:06 +00:00
parent 7e6d70d0b1
commit 3ce27f13b9

View File

@ -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,
};