3
* Copyright (c) 2003 Fabrice Bellard.
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
* - add 2, 4 and 16 bit depth support
23
* - use filters when generating a png (better compression)
31
#define PNG_COLOR_MASK_PALETTE 1
32
#define PNG_COLOR_MASK_COLOR 2
33
#define PNG_COLOR_MASK_ALPHA 4
35
#define PNG_COLOR_TYPE_GRAY 0
36
#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
37
#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR)
38
#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
39
#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
41
#define PNG_FILTER_VALUE_NONE 0
42
#define PNG_FILTER_VALUE_SUB 1
43
#define PNG_FILTER_VALUE_UP 2
44
#define PNG_FILTER_VALUE_AVG 3
45
#define PNG_FILTER_VALUE_PAETH 4
47
#define PNG_IHDR 0x0001
48
#define PNG_IDAT 0x0002
49
#define PNG_ALLIMAGE 0x0004
50
#define PNG_PLTE 0x0008
54
#define IOBUF_SIZE 4096
56
typedef struct PNGContext {
58
uint8_t *bytestream_start;
59
uint8_t *bytestream_end;
75
uint32_t palette[256];
80
int crow_size; /* compressed row size (include filter type) */
81
int row_size; /* decompressed row size */
82
int pass_row_size; /* decompress row size of the current pass */
85
uint8_t buf[IOBUF_SIZE];
88
static unsigned int get32(uint8_t **b){
90
return ((*b)[-4]<<24) + ((*b)[-3]<<16) + ((*b)[-2]<<8) + (*b)[-1];
93
static void put32(uint8_t **b, unsigned int v){
100
static const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
102
/* Mask to determine which y pixels are valid in a pass */
103
static const uint8_t png_pass_ymask[NB_PASSES] = {
104
0x80, 0x80, 0x08, 0x88, 0x22, 0xaa, 0x55,
107
/* Mask to determine which y pixels can be written in a pass */
108
static const uint8_t png_pass_dsp_ymask[NB_PASSES] = {
109
0xff, 0xff, 0x0f, 0xcc, 0x33, 0xff, 0x55,
112
/* minimum x value */
113
static const uint8_t png_pass_xmin[NB_PASSES] = {
117
/* x shift to get row width */
118
static const uint8_t png_pass_xshift[NB_PASSES] = {
122
/* Mask to determine which pixels are valid in a pass */
123
static const uint8_t png_pass_mask[NB_PASSES] = {
124
0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff
127
/* Mask to determine which pixels to overwrite while displaying */
128
static const uint8_t png_pass_dsp_mask[NB_PASSES] = {
129
0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff
132
static int png_probe(AVProbeData *pd)
134
if (pd->buf_size >= 8 &&
135
memcmp(pd->buf, pngsig, 8) == 0)
136
return AVPROBE_SCORE_MAX;
141
static void *png_zalloc(void *opaque, unsigned int items, unsigned int size)
143
if(items >= UINT_MAX / size)
145
return av_malloc(items * size);
148
static void png_zfree(void *opaque, void *ptr)
153
static int png_get_nb_channels(int color_type)
157
if ((color_type & (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)) ==
158
PNG_COLOR_MASK_COLOR)
160
if (color_type & PNG_COLOR_MASK_ALPHA)
165
/* compute the row size of an interleaved pass */
166
static int png_pass_row_size(int pass, int bits_per_pixel, int width)
168
int shift, xmin, pass_width;
170
xmin = png_pass_xmin[pass];
173
shift = png_pass_xshift[pass];
174
pass_width = (width - xmin + (1 << shift) - 1) >> shift;
175
return (pass_width * bits_per_pixel + 7) >> 3;
178
/* NOTE: we try to construct a good looking image at each pass. width
179
is the original image width. We also do pixel format convertion at
181
static void png_put_interlaced_row(uint8_t *dst, int width,
182
int bits_per_pixel, int pass,
183
int color_type, const uint8_t *src)
185
int x, mask, dsp_mask, j, src_x, b, bpp;
189
mask = png_pass_mask[pass];
190
dsp_mask = png_pass_dsp_mask[pass];
191
switch(bits_per_pixel) {
193
/* we must intialize the line to zero before writing to it */
195
memset(dst, 0, (width + 7) >> 3);
197
for(x = 0; x < width; x++) {
199
if ((dsp_mask << j) & 0x80) {
200
b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1;
201
dst[x >> 3] |= b << (7 - j);
203
if ((mask << j) & 0x80)
208
bpp = bits_per_pixel >> 3;
211
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
212
for(x = 0; x < width; x++) {
214
if ((dsp_mask << j) & 0x80) {
215
*(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2];
218
if ((mask << j) & 0x80)
222
for(x = 0; x < width; x++) {
224
if ((dsp_mask << j) & 0x80) {
228
if ((mask << j) & 0x80)
236
static void png_get_interlaced_row(uint8_t *dst, int row_size,
237
int bits_per_pixel, int pass,
238
const uint8_t *src, int width)
240
int x, mask, dst_x, j, b, bpp;
244
mask = png_pass_mask[pass];
245
switch(bits_per_pixel) {
247
memset(dst, 0, row_size);
249
for(x = 0; x < width; x++) {
251
if ((mask << j) & 0x80) {
252
b = (src[x >> 3] >> (7 - j)) & 1;
253
dst[dst_x >> 3] |= b << (7 - (dst_x & 7));
259
bpp = bits_per_pixel >> 3;
262
for(x = 0; x < width; x++) {
264
if ((mask << j) & 0x80) {
275
/* NOTE: 'dst' can be equal to 'last' */
276
static void png_filter_row(uint8_t *dst, int filter_type,
277
uint8_t *src, uint8_t *last, int size, int bpp)
281
switch(filter_type) {
282
case PNG_FILTER_VALUE_NONE:
283
memcpy(dst, src, size);
285
case PNG_FILTER_VALUE_SUB:
286
for(i = 0; i < bpp; i++) {
289
for(i = bpp; i < size; i++) {
294
case PNG_FILTER_VALUE_UP:
295
for(i = 0; i < size; i++) {
300
case PNG_FILTER_VALUE_AVG:
301
for(i = 0; i < bpp; i++) {
305
for(i = bpp; i < size; i++) {
306
p = ((dst[i - bpp] + last[i]) >> 1);
310
case PNG_FILTER_VALUE_PAETH:
311
for(i = 0; i < bpp; i++) {
315
for(i = bpp; i < size; i++) {
316
int a, b, c, pa, pb, pc;
329
if (pa <= pb && pa <= pc)
341
static void convert_from_rgba32(uint8_t *dst, const uint8_t *src, int width)
348
for(j = 0; j < width; j++) {
349
v = ((uint32_t *)src)[j];
358
static void convert_to_rgba32(uint8_t *dst, const uint8_t *src, int width)
361
unsigned int r, g, b, a;
363
for(j = 0;j < width; j++) {
368
*(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b;
374
/* process exactly one decompressed row */
375
static void png_handle_row(PNGContext *s)
377
uint8_t *ptr, *last_row;
380
if (!s->interlace_type) {
381
ptr = s->image_buf + s->image_linesize * s->y;
382
/* need to swap bytes correctly for RGB_ALPHA */
383
if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
384
png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
385
s->last_row, s->row_size, s->bpp);
386
memcpy(s->last_row, s->tmp_row, s->row_size);
387
convert_to_rgba32(ptr, s->tmp_row, s->width);
389
/* in normal case, we avoid one copy */
391
last_row = s->last_row;
393
last_row = ptr - s->image_linesize;
395
png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1,
396
last_row, s->row_size, s->bpp);
399
if (s->y == s->height) {
400
s->state |= PNG_ALLIMAGE;
405
ptr = s->image_buf + s->image_linesize * s->y;
406
if ((png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
407
/* if we already read one row, it is time to stop to
408
wait for the next one */
411
png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
412
s->last_row, s->pass_row_size, s->bpp);
413
memcpy(s->last_row, s->tmp_row, s->pass_row_size);
416
if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
417
/* NOTE: rgba32 is handled directly in png_put_interlaced_row */
418
png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,
419
s->color_type, s->last_row);
422
if (s->y == s->height) {
424
if (s->pass == NB_PASSES - 1) {
425
s->state |= PNG_ALLIMAGE;
430
s->pass_row_size = png_pass_row_size(s->pass,
433
s->crow_size = s->pass_row_size + 1;
434
if (s->pass_row_size != 0)
436
/* skip pass if empty row */
445
static int png_decode_idat(PNGContext *s, int length)
448
s->zstream.avail_in = length;
449
s->zstream.next_in = s->bytestream;
450
s->bytestream += length;
452
if(s->bytestream > s->bytestream_end)
455
/* decode one line if possible */
456
while (s->zstream.avail_in > 0) {
457
ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
458
if (ret != Z_OK && ret != Z_STREAM_END) {
461
if (s->zstream.avail_out == 0) {
462
if (!(s->state & PNG_ALLIMAGE)) {
465
s->zstream.avail_out = s->crow_size;
466
s->zstream.next_out = s->crow_buf;
472
static int decode_frame(AVCodecContext *avctx,
473
void *data, int *data_size,
474
uint8_t *buf, int buf_size)
476
PNGContext * const s = avctx->priv_data;
477
AVFrame *picture = data;
478
AVFrame * const p= (AVFrame*)&s->picture;
479
uint32_t tag, length;
484
s->bytestream_end= buf + buf_size;
486
/* check signature */
487
if (memcmp(s->bytestream, pngsig, 8) != 0)
492
// memset(s, 0, sizeof(PNGContext));
494
s->zstream.zalloc = png_zalloc;
495
s->zstream.zfree = png_zfree;
496
s->zstream.opaque = NULL;
497
ret = inflateInit(&s->zstream);
502
if (s->bytestream >= s->bytestream_end)
504
length = get32(&s->bytestream);
505
if (length > 0x7fffffff)
507
tag32 = get32(&s->bytestream);
508
tag = bswap_32(tag32);
510
printf("png: tag=%c%c%c%c length=%u\n",
513
((tag >> 16) & 0xff),
514
((tag >> 24) & 0xff), length);
517
case MKTAG('I', 'H', 'D', 'R'):
520
s->width = get32(&s->bytestream);
521
s->height = get32(&s->bytestream);
522
if(avcodec_check_dimensions(avctx, s->width, s->height)){
523
s->width= s->height= 0;
526
s->bit_depth = *s->bytestream++;
527
s->color_type = *s->bytestream++;
528
s->compression_type = *s->bytestream++;
529
s->filter_type = *s->bytestream++;
530
s->interlace_type = *s->bytestream++;
531
crc = get32(&s->bytestream);
532
s->state |= PNG_IHDR;
534
printf("width=%d height=%d depth=%d color_type=%d compression_type=%d filter_type=%d interlace_type=%d\n",
535
s->width, s->height, s->bit_depth, s->color_type,
536
s->compression_type, s->filter_type, s->interlace_type);
539
case MKTAG('I', 'D', 'A', 'T'):
540
if (!(s->state & PNG_IHDR))
542
if (!(s->state & PNG_IDAT)) {
543
/* init image info */
544
avctx->width = s->width;
545
avctx->height = s->height;
547
s->channels = png_get_nb_channels(s->color_type);
548
s->bits_per_pixel = s->bit_depth * s->channels;
549
s->bpp = (s->bits_per_pixel + 7) >> 3;
550
s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;
552
if (s->bit_depth == 8 &&
553
s->color_type == PNG_COLOR_TYPE_RGB) {
554
avctx->pix_fmt = PIX_FMT_RGB24;
555
} else if (s->bit_depth == 8 &&
556
s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
557
avctx->pix_fmt = PIX_FMT_RGBA32;
558
} else if (s->bit_depth == 8 &&
559
s->color_type == PNG_COLOR_TYPE_GRAY) {
560
avctx->pix_fmt = PIX_FMT_GRAY8;
561
} else if (s->bit_depth == 1 &&
562
s->color_type == PNG_COLOR_TYPE_GRAY) {
563
avctx->pix_fmt = PIX_FMT_MONOBLACK;
564
} else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
565
avctx->pix_fmt = PIX_FMT_PAL8;
570
avctx->release_buffer(avctx, p);
573
if(avctx->get_buffer(avctx, p) < 0){
574
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
577
p->pict_type= FF_I_TYPE;
579
p->interlaced_frame = !!s->interlace_type;
581
/* compute the compressed row size */
582
if (!s->interlace_type) {
583
s->crow_size = s->row_size + 1;
586
s->pass_row_size = png_pass_row_size(s->pass,
589
s->crow_size = s->pass_row_size + 1;
592
printf("row_size=%d crow_size =%d\n",
593
s->row_size, s->crow_size);
595
s->image_buf = p->data[0];
596
s->image_linesize = p->linesize[0];
597
/* copy the palette if needed */
598
if (s->color_type == PNG_COLOR_TYPE_PALETTE)
599
memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
600
/* empty row is used if differencing to the first row */
601
s->last_row = av_mallocz(s->row_size);
604
if (s->interlace_type ||
605
s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
606
s->tmp_row = av_malloc(s->row_size);
611
s->crow_buf = av_malloc(s->row_size + 1);
614
s->zstream.avail_out = s->crow_size;
615
s->zstream.next_out = s->crow_buf;
617
s->state |= PNG_IDAT;
618
if (png_decode_idat(s, length) < 0)
621
crc = get32(&s->bytestream);
623
case MKTAG('P', 'L', 'T', 'E'):
627
if ((length % 3) != 0 || length > 256 * 3)
629
/* read the palette */
632
r = *s->bytestream++;
633
g = *s->bytestream++;
634
b = *s->bytestream++;
635
s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
638
s->palette[i] = (0xff << 24);
640
s->state |= PNG_PLTE;
641
crc = get32(&s->bytestream);
644
case MKTAG('t', 'R', 'N', 'S'):
648
/* read the transparency. XXX: Only palette mode supported */
649
if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
651
!(s->state & PNG_PLTE))
653
for(i=0;i<length;i++) {
654
v = *s->bytestream++;
655
s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
657
crc = get32(&s->bytestream);
660
case MKTAG('I', 'E', 'N', 'D'):
661
if (!(s->state & PNG_ALLIMAGE))
663
crc = get32(&s->bytestream);
668
s->bytestream += length + 4;
673
*picture= *(AVFrame*)&s->picture;
674
*data_size = sizeof(AVPicture);
676
ret = s->bytestream - s->bytestream_start;
678
inflateEnd(&s->zstream);
679
av_freep(&s->crow_buf);
680
av_freep(&s->last_row);
681
av_freep(&s->tmp_row);
688
static void png_write_chunk(uint8_t **f, uint32_t tag,
689
const uint8_t *buf, int length)
695
crc = crc32(0, Z_NULL, 0);
697
tagbuf[1] = tag >> 8;
698
tagbuf[2] = tag >> 16;
699
tagbuf[3] = tag >> 24;
700
crc = crc32(crc, tagbuf, 4);
701
put32(f, bswap_32(tag));
703
crc = crc32(crc, buf, length);
704
memcpy(*f, buf, length);
710
/* XXX: use avcodec generic function ? */
711
static void to_be32(uint8_t *p, uint32_t v)
719
/* XXX: do filtering */
720
static int png_write_row(PNGContext *s, const uint8_t *data, int size)
724
s->zstream.avail_in = size;
725
s->zstream.next_in = (uint8_t *)data;
726
while (s->zstream.avail_in > 0) {
727
ret = deflate(&s->zstream, Z_NO_FLUSH);
730
if (s->zstream.avail_out == 0) {
731
if(s->bytestream_end - s->bytestream > IOBUF_SIZE + 100)
732
png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, IOBUF_SIZE);
733
s->zstream.avail_out = IOBUF_SIZE;
734
s->zstream.next_out = s->buf;
740
static int common_init(AVCodecContext *avctx){
741
PNGContext *s = avctx->priv_data;
743
avcodec_get_frame_defaults((AVFrame*)&s->picture);
744
avctx->coded_frame= (AVFrame*)&s->picture;
750
static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
751
PNGContext *s = avctx->priv_data;
752
AVFrame *pict = data;
753
AVFrame * const p= (AVFrame*)&s->picture;
754
int bit_depth, color_type, y, len, row_size, ret, is_progressive;
755
int bits_per_pixel, pass_row_size;
757
uint8_t *crow_buf = NULL;
758
uint8_t *tmp_buf = NULL;
761
p->pict_type= FF_I_TYPE;
766
s->bytestream_end= buf+buf_size;
768
is_progressive = !!(avctx->flags & CODEC_FLAG_INTERLACED_DCT);
769
switch(avctx->pix_fmt) {
772
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
776
color_type = PNG_COLOR_TYPE_RGB;
780
color_type = PNG_COLOR_TYPE_GRAY;
782
case PIX_FMT_MONOBLACK:
784
color_type = PNG_COLOR_TYPE_GRAY;
788
color_type = PNG_COLOR_TYPE_PALETTE;
793
bits_per_pixel = png_get_nb_channels(color_type) * bit_depth;
794
row_size = (avctx->width * bits_per_pixel + 7) >> 3;
796
s->zstream.zalloc = png_zalloc;
797
s->zstream.zfree = png_zfree;
798
s->zstream.opaque = NULL;
799
ret = deflateInit2(&s->zstream, Z_DEFAULT_COMPRESSION,
800
Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY);
803
crow_buf = av_malloc(row_size + 1);
806
if (is_progressive) {
807
tmp_buf = av_malloc(row_size + 1);
812
/* write png header */
813
memcpy(s->bytestream, pngsig, 8);
816
to_be32(s->buf, avctx->width);
817
to_be32(s->buf + 4, avctx->height);
818
s->buf[8] = bit_depth;
819
s->buf[9] = color_type;
820
s->buf[10] = 0; /* compression type */
821
s->buf[11] = 0; /* filter type */
822
s->buf[12] = is_progressive; /* interlace type */
824
png_write_chunk(&s->bytestream, MKTAG('I', 'H', 'D', 'R'), s->buf, 13);
826
/* put the palette if needed */
827
if (color_type == PNG_COLOR_TYPE_PALETTE) {
828
int has_alpha, alpha, i;
833
palette = (uint32_t *)p->data[1];
835
alpha_ptr = s->buf + 256 * 3;
837
for(i = 0; i < 256; i++) {
842
*alpha_ptr++ = alpha;
848
png_write_chunk(&s->bytestream, MKTAG('P', 'L', 'T', 'E'), s->buf, 256 * 3);
850
png_write_chunk(&s->bytestream, MKTAG('t', 'R', 'N', 'S'), s->buf + 256 * 3, 256);
854
/* now put each row */
855
s->zstream.avail_out = IOBUF_SIZE;
856
s->zstream.next_out = s->buf;
857
if (is_progressive) {
861
for(pass = 0; pass < NB_PASSES; pass++) {
862
/* NOTE: a pass is completely omited if no pixels would be
864
pass_row_size = png_pass_row_size(pass, bits_per_pixel, avctx->width);
865
if (pass_row_size > 0) {
866
for(y = 0; y < avctx->height; y++) {
867
if ((png_pass_ymask[pass] << (y & 7)) & 0x80) {
868
ptr = p->data[0] + y * p->linesize[0];
869
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
870
convert_from_rgba32(tmp_buf, ptr, avctx->width);
875
png_get_interlaced_row(crow_buf + 1, pass_row_size,
876
bits_per_pixel, pass,
878
crow_buf[0] = PNG_FILTER_VALUE_NONE;
879
png_write_row(s, crow_buf, pass_row_size + 1);
885
for(y = 0; y < avctx->height; y++) {
886
ptr = p->data[0] + y * p->linesize[0];
887
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
888
convert_from_rgba32(crow_buf + 1, ptr, avctx->width);
890
memcpy(crow_buf + 1, ptr, row_size);
891
crow_buf[0] = PNG_FILTER_VALUE_NONE;
892
png_write_row(s, crow_buf, row_size + 1);
895
/* compress last bytes */
897
ret = deflate(&s->zstream, Z_FINISH);
898
if (ret == Z_OK || ret == Z_STREAM_END) {
899
len = IOBUF_SIZE - s->zstream.avail_out;
900
if (len > 0 && s->bytestream_end - s->bytestream > len + 100) {
901
png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, len);
903
s->zstream.avail_out = IOBUF_SIZE;
904
s->zstream.next_out = s->buf;
905
if (ret == Z_STREAM_END)
911
png_write_chunk(&s->bytestream, MKTAG('I', 'E', 'N', 'D'), NULL, 0);
913
ret = s->bytestream - s->bytestream_start;
917
deflateEnd(&s->zstream);
924
AVCodec png_decoder = {
933
0 /*CODEC_CAP_DR1*/ /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
937
#ifdef CONFIG_PNG_ENCODER
938
AVCodec png_encoder = {
946
.pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA32, PIX_FMT_PAL8, PIX_FMT_GRAY8, PIX_FMT_MONOBLACK, -1},
948
#endif // CONFIG_PNG_ENCODER