1/*
2 * PNG image format
3 * Copyright (c) 2003 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#include "avcodec.h"
22#include "bytestream.h"
23#include "png.h"
24#include "dsputil.h"
25
26/* TODO:
27 * - add 2, 4 and 16 bit depth support
28 */
29
30#include <zlib.h>
31
32//#define DEBUG
33
34typedef struct PNGDecContext {
35    DSPContext dsp;
36
37    const uint8_t *bytestream;
38    const uint8_t *bytestream_start;
39    const uint8_t *bytestream_end;
40    AVFrame picture;
41
42    int state;
43    int width, height;
44    int bit_depth;
45    int color_type;
46    int compression_type;
47    int interlace_type;
48    int filter_type;
49    int channels;
50    int bits_per_pixel;
51    int bpp;
52
53    uint8_t *image_buf;
54    int image_linesize;
55    uint32_t palette[256];
56    uint8_t *crow_buf;
57    uint8_t *last_row;
58    uint8_t *tmp_row;
59    int pass;
60    int crow_size; /* compressed row size (include filter type) */
61    int row_size; /* decompressed row size */
62    int pass_row_size; /* decompress row size of the current pass */
63    int y;
64    z_stream zstream;
65} PNGDecContext;
66
67/* Mask to determine which y pixels can be written in a pass */
68static const uint8_t png_pass_dsp_ymask[NB_PASSES] = {
69    0xff, 0xff, 0x0f, 0xcc, 0x33, 0xff, 0x55,
70};
71
72/* Mask to determine which pixels to overwrite while displaying */
73static const uint8_t png_pass_dsp_mask[NB_PASSES] = {
74    0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff
75};
76
77/* NOTE: we try to construct a good looking image at each pass. width
78   is the original image width. We also do pixel format conversion at
79   this stage */
80static void png_put_interlaced_row(uint8_t *dst, int width,
81                                   int bits_per_pixel, int pass,
82                                   int color_type, const uint8_t *src)
83{
84    int x, mask, dsp_mask, j, src_x, b, bpp;
85    uint8_t *d;
86    const uint8_t *s;
87
88    mask = ff_png_pass_mask[pass];
89    dsp_mask = png_pass_dsp_mask[pass];
90    switch(bits_per_pixel) {
91    case 1:
92        /* we must initialize the line to zero before writing to it */
93        if (pass == 0)
94            memset(dst, 0, (width + 7) >> 3);
95        src_x = 0;
96        for(x = 0; x < width; x++) {
97            j = (x & 7);
98            if ((dsp_mask << j) & 0x80) {
99                b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1;
100                dst[x >> 3] |= b << (7 - j);
101            }
102            if ((mask << j) & 0x80)
103                src_x++;
104        }
105        break;
106    default:
107        bpp = bits_per_pixel >> 3;
108        d = dst;
109        s = src;
110        if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
111            for(x = 0; x < width; x++) {
112                j = x & 7;
113                if ((dsp_mask << j) & 0x80) {
114                    *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2];
115                }
116                d += bpp;
117                if ((mask << j) & 0x80)
118                    s += bpp;
119            }
120        } else {
121            for(x = 0; x < width; x++) {
122                j = x & 7;
123                if ((dsp_mask << j) & 0x80) {
124                    memcpy(d, s, bpp);
125                }
126                d += bpp;
127                if ((mask << j) & 0x80)
128                    s += bpp;
129            }
130        }
131        break;
132    }
133}
134
135void ff_add_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w, int bpp)
136{
137    int i;
138    for(i = 0; i < w; i++) {
139        int a, b, c, p, pa, pb, pc;
140
141        a = dst[i - bpp];
142        b = top[i];
143        c = top[i - bpp];
144
145        p = b - c;
146        pc = a - c;
147
148        pa = abs(p);
149        pb = abs(pc);
150        pc = abs(p + pc);
151
152        if (pa <= pb && pa <= pc)
153            p = a;
154        else if (pb <= pc)
155            p = b;
156        else
157            p = c;
158        dst[i] = p + src[i];
159    }
160}
161
162#define UNROLL1(bpp, op) {\
163                 r = dst[0];\
164    if(bpp >= 2) g = dst[1];\
165    if(bpp >= 3) b = dst[2];\
166    if(bpp >= 4) a = dst[3];\
167    for(; i < size; i+=bpp) {\
168        dst[i+0] = r = op(r, src[i+0], last[i+0]);\
169        if(bpp == 1) continue;\
170        dst[i+1] = g = op(g, src[i+1], last[i+1]);\
171        if(bpp == 2) continue;\
172        dst[i+2] = b = op(b, src[i+2], last[i+2]);\
173        if(bpp == 3) continue;\
174        dst[i+3] = a = op(a, src[i+3], last[i+3]);\
175    }\
176}
177
178#define UNROLL_FILTER(op)\
179         if(bpp == 1) UNROLL1(1, op)\
180    else if(bpp == 2) UNROLL1(2, op)\
181    else if(bpp == 3) UNROLL1(3, op)\
182    else if(bpp == 4) UNROLL1(4, op)\
183
184/* NOTE: 'dst' can be equal to 'last' */
185static void png_filter_row(DSPContext *dsp, uint8_t *dst, int filter_type,
186                           uint8_t *src, uint8_t *last, int size, int bpp)
187{
188    int i, p, r, g, b, a;
189
190    switch(filter_type) {
191    case PNG_FILTER_VALUE_NONE:
192        memcpy(dst, src, size);
193        break;
194    case PNG_FILTER_VALUE_SUB:
195        for(i = 0; i < bpp; i++) {
196            dst[i] = src[i];
197        }
198        if(bpp == 4) {
199            p = *(int*)dst;
200            for(; i < size; i+=bpp) {
201                int s = *(int*)(src+i);
202                p = ((s&0x7f7f7f7f) + (p&0x7f7f7f7f)) ^ ((s^p)&0x80808080);
203                *(int*)(dst+i) = p;
204            }
205        } else {
206#define OP_SUB(x,s,l) x+s
207            UNROLL_FILTER(OP_SUB);
208        }
209        break;
210    case PNG_FILTER_VALUE_UP:
211        dsp->add_bytes_l2(dst, src, last, size);
212        break;
213    case PNG_FILTER_VALUE_AVG:
214        for(i = 0; i < bpp; i++) {
215            p = (last[i] >> 1);
216            dst[i] = p + src[i];
217        }
218#define OP_AVG(x,s,l) (((x + l) >> 1) + s) & 0xff
219        UNROLL_FILTER(OP_AVG);
220        break;
221    case PNG_FILTER_VALUE_PAETH:
222        for(i = 0; i < bpp; i++) {
223            p = last[i];
224            dst[i] = p + src[i];
225        }
226        if(bpp > 1 && size > 4) {
227            // would write off the end of the array if we let it process the last pixel with bpp=3
228            int w = bpp==4 ? size : size-3;
229            dsp->add_png_paeth_prediction(dst+i, src+i, last+i, w-i, bpp);
230            i = w;
231        }
232        ff_add_png_paeth_prediction(dst+i, src+i, last+i, size-i, bpp);
233        break;
234    }
235}
236
237static av_always_inline void convert_to_rgb32_loco(uint8_t *dst, const uint8_t *src, int width, int loco)
238{
239    int j;
240    unsigned int r, g, b, a;
241
242    for(j = 0;j < width; j++) {
243        r = src[0];
244        g = src[1];
245        b = src[2];
246        a = src[3];
247        if(loco) {
248            r = (r+g)&0xff;
249            b = (b+g)&0xff;
250        }
251        *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b;
252        dst += 4;
253        src += 4;
254    }
255}
256
257static void convert_to_rgb32(uint8_t *dst, const uint8_t *src, int width, int loco)
258{
259    if(loco)
260        convert_to_rgb32_loco(dst, src, width, 1);
261    else
262        convert_to_rgb32_loco(dst, src, width, 0);
263}
264
265static void deloco_rgb24(uint8_t *dst, int size)
266{
267    int i;
268    for(i=0; i<size; i+=3) {
269        int g = dst[i+1];
270        dst[i+0] += g;
271        dst[i+2] += g;
272    }
273}
274
275/* process exactly one decompressed row */
276static void png_handle_row(PNGDecContext *s)
277{
278    uint8_t *ptr, *last_row;
279    int got_line;
280
281    if (!s->interlace_type) {
282        ptr = s->image_buf + s->image_linesize * s->y;
283        /* need to swap bytes correctly for RGB_ALPHA */
284        if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
285            png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
286                           s->last_row, s->row_size, s->bpp);
287            convert_to_rgb32(ptr, s->tmp_row, s->width, s->filter_type == PNG_FILTER_TYPE_LOCO);
288            FFSWAP(uint8_t*, s->last_row, s->tmp_row);
289        } else {
290            /* in normal case, we avoid one copy */
291            if (s->y == 0)
292                last_row = s->last_row;
293            else
294                last_row = ptr - s->image_linesize;
295
296            png_filter_row(&s->dsp, ptr, s->crow_buf[0], s->crow_buf + 1,
297                           last_row, s->row_size, s->bpp);
298        }
299        /* loco lags by 1 row so that it doesn't interfere with top prediction */
300        if (s->filter_type == PNG_FILTER_TYPE_LOCO &&
301            s->color_type == PNG_COLOR_TYPE_RGB && s->y > 0)
302            deloco_rgb24(ptr - s->image_linesize, s->row_size);
303        s->y++;
304        if (s->y == s->height) {
305            s->state |= PNG_ALLIMAGE;
306            if (s->filter_type == PNG_FILTER_TYPE_LOCO &&
307                s->color_type == PNG_COLOR_TYPE_RGB)
308                deloco_rgb24(ptr, s->row_size);
309        }
310    } else {
311        got_line = 0;
312        for(;;) {
313            ptr = s->image_buf + s->image_linesize * s->y;
314            if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
315                /* if we already read one row, it is time to stop to
316                   wait for the next one */
317                if (got_line)
318                    break;
319                png_filter_row(&s->dsp, s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
320                               s->last_row, s->pass_row_size, s->bpp);
321                FFSWAP(uint8_t*, s->last_row, s->tmp_row);
322                got_line = 1;
323            }
324            if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
325                /* NOTE: RGB32 is handled directly in png_put_interlaced_row */
326                png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,
327                                       s->color_type, s->last_row);
328            }
329            s->y++;
330            if (s->y == s->height) {
331                for(;;) {
332                    if (s->pass == NB_PASSES - 1) {
333                        s->state |= PNG_ALLIMAGE;
334                        goto the_end;
335                    } else {
336                        s->pass++;
337                        s->y = 0;
338                        s->pass_row_size = ff_png_pass_row_size(s->pass,
339                                                             s->bits_per_pixel,
340                                                             s->width);
341                        s->crow_size = s->pass_row_size + 1;
342                        if (s->pass_row_size != 0)
343                            break;
344                        /* skip pass if empty row */
345                    }
346                }
347            }
348        }
349    the_end: ;
350    }
351}
352
353static int png_decode_idat(PNGDecContext *s, int length)
354{
355    int ret;
356    s->zstream.avail_in = length;
357    s->zstream.next_in = s->bytestream;
358    s->bytestream += length;
359
360    if(s->bytestream > s->bytestream_end)
361        return -1;
362
363    /* decode one line if possible */
364    while (s->zstream.avail_in > 0) {
365        ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
366        if (ret != Z_OK && ret != Z_STREAM_END) {
367            return -1;
368        }
369        if (s->zstream.avail_out == 0) {
370            if (!(s->state & PNG_ALLIMAGE)) {
371                png_handle_row(s);
372            }
373            s->zstream.avail_out = s->crow_size;
374            s->zstream.next_out = s->crow_buf;
375        }
376    }
377    return 0;
378}
379
380static int decode_frame(AVCodecContext *avctx,
381                        void *data, int *data_size,
382                        const uint8_t *buf, int buf_size)
383{
384    PNGDecContext * const s = avctx->priv_data;
385    AVFrame *picture = data;
386    AVFrame * const p= &s->picture;
387    uint32_t tag, length;
388    int ret, crc;
389
390    s->bytestream_start=
391    s->bytestream= buf;
392    s->bytestream_end= buf + buf_size;
393
394    /* check signature */
395    if (memcmp(s->bytestream, ff_pngsig, 8) != 0 &&
396        memcmp(s->bytestream, ff_mngsig, 8) != 0)
397        return -1;
398    s->bytestream+= 8;
399    s->y=
400    s->state=0;
401//    memset(s, 0, sizeof(PNGDecContext));
402    /* init the zlib */
403    s->zstream.zalloc = ff_png_zalloc;
404    s->zstream.zfree = ff_png_zfree;
405    s->zstream.opaque = NULL;
406    ret = inflateInit(&s->zstream);
407    if (ret != Z_OK)
408        return -1;
409    for(;;) {
410        int tag32;
411        if (s->bytestream >= s->bytestream_end)
412            goto fail;
413        length = bytestream_get_be32(&s->bytestream);
414        if (length > 0x7fffffff)
415            goto fail;
416        tag32 = bytestream_get_be32(&s->bytestream);
417        tag = bswap_32(tag32);
418#ifdef DEBUG
419        av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
420               (tag & 0xff),
421               ((tag >> 8) & 0xff),
422               ((tag >> 16) & 0xff),
423               ((tag >> 24) & 0xff), length);
424#endif
425        switch(tag) {
426        case MKTAG('I', 'H', 'D', 'R'):
427            if (length != 13)
428                goto fail;
429            s->width = bytestream_get_be32(&s->bytestream);
430            s->height = bytestream_get_be32(&s->bytestream);
431            if(avcodec_check_dimensions(avctx, s->width, s->height)){
432                s->width= s->height= 0;
433                goto fail;
434            }
435            s->bit_depth = *s->bytestream++;
436            s->color_type = *s->bytestream++;
437            s->compression_type = *s->bytestream++;
438            s->filter_type = *s->bytestream++;
439            s->interlace_type = *s->bytestream++;
440            crc = bytestream_get_be32(&s->bytestream);
441            s->state |= PNG_IHDR;
442#ifdef DEBUG
443            av_log(avctx, AV_LOG_DEBUG, "width=%d height=%d depth=%d color_type=%d compression_type=%d filter_type=%d interlace_type=%d\n",
444                   s->width, s->height, s->bit_depth, s->color_type,
445                   s->compression_type, s->filter_type, s->interlace_type);
446#endif
447            break;
448        case MKTAG('I', 'D', 'A', 'T'):
449            if (!(s->state & PNG_IHDR))
450                goto fail;
451            if (!(s->state & PNG_IDAT)) {
452                /* init image info */
453                avctx->width = s->width;
454                avctx->height = s->height;
455
456                s->channels = ff_png_get_nb_channels(s->color_type);
457                s->bits_per_pixel = s->bit_depth * s->channels;
458                s->bpp = (s->bits_per_pixel + 7) >> 3;
459                s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;
460
461                if (s->bit_depth == 8 &&
462                    s->color_type == PNG_COLOR_TYPE_RGB) {
463                    avctx->pix_fmt = PIX_FMT_RGB24;
464                } else if (s->bit_depth == 8 &&
465                           s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
466                    avctx->pix_fmt = PIX_FMT_RGB32;
467                } else if (s->bit_depth == 8 &&
468                           s->color_type == PNG_COLOR_TYPE_GRAY) {
469                    avctx->pix_fmt = PIX_FMT_GRAY8;
470                } else if (s->bit_depth == 16 &&
471                           s->color_type == PNG_COLOR_TYPE_GRAY) {
472                    avctx->pix_fmt = PIX_FMT_GRAY16BE;
473                } else if (s->bit_depth == 1 &&
474                           s->color_type == PNG_COLOR_TYPE_GRAY) {
475                    avctx->pix_fmt = PIX_FMT_MONOBLACK;
476                } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
477                    avctx->pix_fmt = PIX_FMT_PAL8;
478                } else {
479                    goto fail;
480                }
481                if(p->data[0])
482                    avctx->release_buffer(avctx, p);
483
484                p->reference= 0;
485                if(avctx->get_buffer(avctx, p) < 0){
486                    av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
487                    goto fail;
488                }
489                p->pict_type= FF_I_TYPE;
490                p->key_frame= 1;
491                p->interlaced_frame = !!s->interlace_type;
492
493                /* compute the compressed row size */
494                if (!s->interlace_type) {
495                    s->crow_size = s->row_size + 1;
496                } else {
497                    s->pass = 0;
498                    s->pass_row_size = ff_png_pass_row_size(s->pass,
499                                                         s->bits_per_pixel,
500                                                         s->width);
501                    s->crow_size = s->pass_row_size + 1;
502                }
503#ifdef DEBUG
504                av_log(avctx, AV_LOG_DEBUG, "row_size=%d crow_size =%d\n",
505                       s->row_size, s->crow_size);
506#endif
507                s->image_buf = p->data[0];
508                s->image_linesize = p->linesize[0];
509                /* copy the palette if needed */
510                if (s->color_type == PNG_COLOR_TYPE_PALETTE)
511                    memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
512                /* empty row is used if differencing to the first row */
513                s->last_row = av_mallocz(s->row_size);
514                if (!s->last_row)
515                    goto fail;
516                if (s->interlace_type ||
517                    s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
518                    s->tmp_row = av_malloc(s->row_size);
519                    if (!s->tmp_row)
520                        goto fail;
521                }
522                /* compressed row */
523                s->crow_buf = av_malloc(s->row_size + 1);
524                if (!s->crow_buf)
525                    goto fail;
526                s->zstream.avail_out = s->crow_size;
527                s->zstream.next_out = s->crow_buf;
528            }
529            s->state |= PNG_IDAT;
530            if (png_decode_idat(s, length) < 0)
531                goto fail;
532            /* skip crc */
533            crc = bytestream_get_be32(&s->bytestream);
534            break;
535        case MKTAG('P', 'L', 'T', 'E'):
536            {
537                int n, i, r, g, b;
538
539                if ((length % 3) != 0 || length > 256 * 3)
540                    goto skip_tag;
541                /* read the palette */
542                n = length / 3;
543                for(i=0;i<n;i++) {
544                    r = *s->bytestream++;
545                    g = *s->bytestream++;
546                    b = *s->bytestream++;
547                    s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
548                }
549                for(;i<256;i++) {
550                    s->palette[i] = (0xff << 24);
551                }
552                s->state |= PNG_PLTE;
553                crc = bytestream_get_be32(&s->bytestream);
554            }
555            break;
556        case MKTAG('t', 'R', 'N', 'S'):
557            {
558                int v, i;
559
560                /* read the transparency. XXX: Only palette mode supported */
561                if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
562                    length > 256 ||
563                    !(s->state & PNG_PLTE))
564                    goto skip_tag;
565                for(i=0;i<length;i++) {
566                    v = *s->bytestream++;
567                    s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
568                }
569                crc = bytestream_get_be32(&s->bytestream);
570            }
571            break;
572        case MKTAG('I', 'E', 'N', 'D'):
573            if (!(s->state & PNG_ALLIMAGE))
574                goto fail;
575            crc = bytestream_get_be32(&s->bytestream);
576            goto exit_loop;
577        default:
578            /* skip tag */
579        skip_tag:
580            s->bytestream += length + 4;
581            break;
582        }
583    }
584 exit_loop:
585    *picture= s->picture;
586    *data_size = sizeof(AVFrame);
587
588    ret = s->bytestream - s->bytestream_start;
589 the_end:
590    inflateEnd(&s->zstream);
591    av_freep(&s->crow_buf);
592    av_freep(&s->last_row);
593    av_freep(&s->tmp_row);
594    return ret;
595 fail:
596    ret = -1;
597    goto the_end;
598}
599
600static av_cold int png_dec_init(AVCodecContext *avctx){
601    PNGDecContext *s = avctx->priv_data;
602
603    avcodec_get_frame_defaults(&s->picture);
604    avctx->coded_frame= &s->picture;
605    dsputil_init(&s->dsp, avctx);
606
607    return 0;
608}
609
610AVCodec png_decoder = {
611    "png",
612    CODEC_TYPE_VIDEO,
613    CODEC_ID_PNG,
614    sizeof(PNGDecContext),
615    png_dec_init,
616    NULL,
617    NULL, //decode_end,
618    decode_frame,
619    0 /*CODEC_CAP_DR1*/ /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
620    NULL,
621    .long_name = NULL_IF_CONFIG_SMALL("PNG image"),
622};
623