separate en/decoder specific parts from png.c
[ffmpeg.git] / libavcodec / pngdec.c
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
25 /* TODO:
26  * - add 2, 4 and 16 bit depth support
27  */
28
29 #include <zlib.h>
30
31 //#define DEBUG
32
33 /* Mask to determine which y pixels can be written in a pass */
34 static const uint8_t png_pass_dsp_ymask[NB_PASSES] = {
35     0xff, 0xff, 0x0f, 0xcc, 0x33, 0xff, 0x55,
36 };
37
38 /* Mask to determine which pixels to overwrite while displaying */
39 static const uint8_t png_pass_dsp_mask[NB_PASSES] = {
40     0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff
41 };
42
43 /* NOTE: we try to construct a good looking image at each pass. width
44    is the original image width. We also do pixel format convertion at
45    this stage */
46 static void png_put_interlaced_row(uint8_t *dst, int width,
47                                    int bits_per_pixel, int pass,
48                                    int color_type, const uint8_t *src)
49 {
50     int x, mask, dsp_mask, j, src_x, b, bpp;
51     uint8_t *d;
52     const uint8_t *s;
53
54     mask = ff_png_pass_mask[pass];
55     dsp_mask = png_pass_dsp_mask[pass];
56     switch(bits_per_pixel) {
57     case 1:
58         /* we must initialize the line to zero before writing to it */
59         if (pass == 0)
60             memset(dst, 0, (width + 7) >> 3);
61         src_x = 0;
62         for(x = 0; x < width; x++) {
63             j = (x & 7);
64             if ((dsp_mask << j) & 0x80) {
65                 b = (src[src_x >> 3] >> (7 - (src_x & 7))) & 1;
66                 dst[x >> 3] |= b << (7 - j);
67             }
68             if ((mask << j) & 0x80)
69                 src_x++;
70         }
71         break;
72     default:
73         bpp = bits_per_pixel >> 3;
74         d = dst;
75         s = src;
76         if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
77             for(x = 0; x < width; x++) {
78                 j = x & 7;
79                 if ((dsp_mask << j) & 0x80) {
80                     *(uint32_t *)d = (s[3] << 24) | (s[0] << 16) | (s[1] << 8) | s[2];
81                 }
82                 d += bpp;
83                 if ((mask << j) & 0x80)
84                     s += bpp;
85             }
86         } else {
87             for(x = 0; x < width; x++) {
88                 j = x & 7;
89                 if ((dsp_mask << j) & 0x80) {
90                     memcpy(d, s, bpp);
91                 }
92                 d += bpp;
93                 if ((mask << j) & 0x80)
94                     s += bpp;
95             }
96         }
97         break;
98     }
99 }
100
101 /* XXX: optimize */
102 /* NOTE: 'dst' can be equal to 'last' */
103 static void png_filter_row(uint8_t *dst, int filter_type,
104                            uint8_t *src, uint8_t *last, int size, int bpp)
105 {
106     int i, p;
107
108     switch(filter_type) {
109     case PNG_FILTER_VALUE_NONE:
110         memcpy(dst, src, size);
111         break;
112     case PNG_FILTER_VALUE_SUB:
113         for(i = 0; i < bpp; i++) {
114             dst[i] = src[i];
115         }
116         for(i = bpp; i < size; i++) {
117             p = dst[i - bpp];
118             dst[i] = p + src[i];
119         }
120         break;
121     case PNG_FILTER_VALUE_UP:
122         for(i = 0; i < size; i++) {
123             p = last[i];
124             dst[i] = p + src[i];
125         }
126         break;
127     case PNG_FILTER_VALUE_AVG:
128         for(i = 0; i < bpp; i++) {
129             p = (last[i] >> 1);
130             dst[i] = p + src[i];
131         }
132         for(i = bpp; i < size; i++) {
133             p = ((dst[i - bpp] + last[i]) >> 1);
134             dst[i] = p + src[i];
135         }
136         break;
137     case PNG_FILTER_VALUE_PAETH:
138         for(i = 0; i < bpp; i++) {
139             p = last[i];
140             dst[i] = p + src[i];
141         }
142         for(i = bpp; i < size; i++) {
143             int a, b, c, pa, pb, pc;
144
145             a = dst[i - bpp];
146             b = last[i];
147             c = last[i - bpp];
148
149             p = b - c;
150             pc = a - c;
151
152             pa = abs(p);
153             pb = abs(pc);
154             pc = abs(p + pc);
155
156             if (pa <= pb && pa <= pc)
157                 p = a;
158             else if (pb <= pc)
159                 p = b;
160             else
161                 p = c;
162             dst[i] = p + src[i];
163         }
164         break;
165     }
166 }
167
168 static void convert_to_rgb32(uint8_t *dst, const uint8_t *src, int width)
169 {
170     int j;
171     unsigned int r, g, b, a;
172
173     for(j = 0;j < width; j++) {
174         r = src[0];
175         g = src[1];
176         b = src[2];
177         a = src[3];
178         *(uint32_t *)dst = (a << 24) | (r << 16) | (g << 8) | b;
179         dst += 4;
180         src += 4;
181     }
182 }
183
184 /* process exactly one decompressed row */
185 static void png_handle_row(PNGContext *s)
186 {
187     uint8_t *ptr, *last_row;
188     int got_line;
189
190     if (!s->interlace_type) {
191         ptr = s->image_buf + s->image_linesize * s->y;
192         /* need to swap bytes correctly for RGB_ALPHA */
193         if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
194             png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
195                            s->last_row, s->row_size, s->bpp);
196             memcpy(s->last_row, s->tmp_row, s->row_size);
197             convert_to_rgb32(ptr, s->tmp_row, s->width);
198         } else {
199             /* in normal case, we avoid one copy */
200             if (s->y == 0)
201                 last_row = s->last_row;
202             else
203                 last_row = ptr - s->image_linesize;
204
205             png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1,
206                            last_row, s->row_size, s->bpp);
207         }
208         s->y++;
209         if (s->y == s->height) {
210             s->state |= PNG_ALLIMAGE;
211         }
212     } else {
213         got_line = 0;
214         for(;;) {
215             ptr = s->image_buf + s->image_linesize * s->y;
216             if ((ff_png_pass_ymask[s->pass] << (s->y & 7)) & 0x80) {
217                 /* if we already read one row, it is time to stop to
218                    wait for the next one */
219                 if (got_line)
220                     break;
221                 png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
222                                s->last_row, s->pass_row_size, s->bpp);
223                 memcpy(s->last_row, s->tmp_row, s->pass_row_size);
224                 got_line = 1;
225             }
226             if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
227                 /* NOTE: RGB32 is handled directly in png_put_interlaced_row */
228                 png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,
229                                        s->color_type, s->last_row);
230             }
231             s->y++;
232             if (s->y == s->height) {
233                 for(;;) {
234                     if (s->pass == NB_PASSES - 1) {
235                         s->state |= PNG_ALLIMAGE;
236                         goto the_end;
237                     } else {
238                         s->pass++;
239                         s->y = 0;
240                         s->pass_row_size = ff_png_pass_row_size(s->pass,
241                                                              s->bits_per_pixel,
242                                                              s->width);
243                         s->crow_size = s->pass_row_size + 1;
244                         if (s->pass_row_size != 0)
245                             break;
246                         /* skip pass if empty row */
247                     }
248                 }
249             }
250         }
251     the_end: ;
252     }
253 }
254
255 static int png_decode_idat(PNGContext *s, int length)
256 {
257     int ret;
258     s->zstream.avail_in = length;
259     s->zstream.next_in = s->bytestream;
260     s->bytestream += length;
261
262     if(s->bytestream > s->bytestream_end)
263         return -1;
264
265     /* decode one line if possible */
266     while (s->zstream.avail_in > 0) {
267         ret = inflate(&s->zstream, Z_PARTIAL_FLUSH);
268         if (ret != Z_OK && ret != Z_STREAM_END) {
269             return -1;
270         }
271         if (s->zstream.avail_out == 0) {
272             if (!(s->state & PNG_ALLIMAGE)) {
273                 png_handle_row(s);
274             }
275             s->zstream.avail_out = s->crow_size;
276             s->zstream.next_out = s->crow_buf;
277         }
278     }
279     return 0;
280 }
281
282 static int decode_frame(AVCodecContext *avctx,
283                         void *data, int *data_size,
284                         uint8_t *buf, int buf_size)
285 {
286     PNGContext * const s = avctx->priv_data;
287     AVFrame *picture = data;
288     AVFrame * const p= (AVFrame*)&s->picture;
289     uint32_t tag, length;
290     int ret, crc;
291
292     s->bytestream_start=
293     s->bytestream= buf;
294     s->bytestream_end= buf + buf_size;
295
296     /* check signature */
297     if (memcmp(s->bytestream, ff_pngsig, 8) != 0)
298         return -1;
299     s->bytestream+= 8;
300     s->y=
301     s->state=0;
302 //    memset(s, 0, sizeof(PNGContext));
303     /* init the zlib */
304     s->zstream.zalloc = ff_png_zalloc;
305     s->zstream.zfree = ff_png_zfree;
306     s->zstream.opaque = NULL;
307     ret = inflateInit(&s->zstream);
308     if (ret != Z_OK)
309         return -1;
310     for(;;) {
311         int tag32;
312         if (s->bytestream >= s->bytestream_end)
313             goto fail;
314         length = bytestream_get_be32(&s->bytestream);
315         if (length > 0x7fffffff)
316             goto fail;
317         tag32 = bytestream_get_be32(&s->bytestream);
318         tag = bswap_32(tag32);
319 #ifdef DEBUG
320         av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
321                (tag & 0xff),
322                ((tag >> 8) & 0xff),
323                ((tag >> 16) & 0xff),
324                ((tag >> 24) & 0xff), length);
325 #endif
326         switch(tag) {
327         case MKTAG('I', 'H', 'D', 'R'):
328             if (length != 13)
329                 goto fail;
330             s->width = bytestream_get_be32(&s->bytestream);
331             s->height = bytestream_get_be32(&s->bytestream);
332             if(avcodec_check_dimensions(avctx, s->width, s->height)){
333                 s->width= s->height= 0;
334                 goto fail;
335             }
336             s->bit_depth = *s->bytestream++;
337             s->color_type = *s->bytestream++;
338             s->compression_type = *s->bytestream++;
339             s->filter_type = *s->bytestream++;
340             s->interlace_type = *s->bytestream++;
341             crc = bytestream_get_be32(&s->bytestream);
342             s->state |= PNG_IHDR;
343 #ifdef DEBUG
344             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",
345                    s->width, s->height, s->bit_depth, s->color_type,
346                    s->compression_type, s->filter_type, s->interlace_type);
347 #endif
348             break;
349         case MKTAG('I', 'D', 'A', 'T'):
350             if (!(s->state & PNG_IHDR))
351                 goto fail;
352             if (!(s->state & PNG_IDAT)) {
353                 /* init image info */
354                 avctx->width = s->width;
355                 avctx->height = s->height;
356
357                 s->channels = ff_png_get_nb_channels(s->color_type);
358                 s->bits_per_pixel = s->bit_depth * s->channels;
359                 s->bpp = (s->bits_per_pixel + 7) >> 3;
360                 s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;
361
362                 if (s->bit_depth == 8 &&
363                     s->color_type == PNG_COLOR_TYPE_RGB) {
364                     avctx->pix_fmt = PIX_FMT_RGB24;
365                 } else if (s->bit_depth == 8 &&
366                            s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
367                     avctx->pix_fmt = PIX_FMT_RGB32;
368                 } else if (s->bit_depth == 8 &&
369                            s->color_type == PNG_COLOR_TYPE_GRAY) {
370                     avctx->pix_fmt = PIX_FMT_GRAY8;
371                 } else if (s->bit_depth == 16 &&
372                            s->color_type == PNG_COLOR_TYPE_GRAY) {
373                     avctx->pix_fmt = PIX_FMT_GRAY16BE;
374                 } else if (s->bit_depth == 1 &&
375                            s->color_type == PNG_COLOR_TYPE_GRAY) {
376                     avctx->pix_fmt = PIX_FMT_MONOBLACK;
377                 } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
378                     avctx->pix_fmt = PIX_FMT_PAL8;
379                 } else {
380                     goto fail;
381                 }
382                 if(p->data[0])
383                     avctx->release_buffer(avctx, p);
384
385                 p->reference= 0;
386                 if(avctx->get_buffer(avctx, p) < 0){
387                     av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
388                     goto fail;
389                 }
390                 p->pict_type= FF_I_TYPE;
391                 p->key_frame= 1;
392                 p->interlaced_frame = !!s->interlace_type;
393
394                 /* compute the compressed row size */
395                 if (!s->interlace_type) {
396                     s->crow_size = s->row_size + 1;
397                 } else {
398                     s->pass = 0;
399                     s->pass_row_size = ff_png_pass_row_size(s->pass,
400                                                          s->bits_per_pixel,
401                                                          s->width);
402                     s->crow_size = s->pass_row_size + 1;
403                 }
404 #ifdef DEBUG
405                 av_log(avctx, AV_LOG_DEBUG, "row_size=%d crow_size =%d\n",
406                        s->row_size, s->crow_size);
407 #endif
408                 s->image_buf = p->data[0];
409                 s->image_linesize = p->linesize[0];
410                 /* copy the palette if needed */
411                 if (s->color_type == PNG_COLOR_TYPE_PALETTE)
412                     memcpy(p->data[1], s->palette, 256 * sizeof(uint32_t));
413                 /* empty row is used if differencing to the first row */
414                 s->last_row = av_mallocz(s->row_size);
415                 if (!s->last_row)
416                     goto fail;
417                 if (s->interlace_type ||
418                     s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
419                     s->tmp_row = av_malloc(s->row_size);
420                     if (!s->tmp_row)
421                         goto fail;
422                 }
423                 /* compressed row */
424                 s->crow_buf = av_malloc(s->row_size + 1);
425                 if (!s->crow_buf)
426                     goto fail;
427                 s->zstream.avail_out = s->crow_size;
428                 s->zstream.next_out = s->crow_buf;
429             }
430             s->state |= PNG_IDAT;
431             if (png_decode_idat(s, length) < 0)
432                 goto fail;
433             /* skip crc */
434             crc = bytestream_get_be32(&s->bytestream);
435             break;
436         case MKTAG('P', 'L', 'T', 'E'):
437             {
438                 int n, i, r, g, b;
439
440                 if ((length % 3) != 0 || length > 256 * 3)
441                     goto skip_tag;
442                 /* read the palette */
443                 n = length / 3;
444                 for(i=0;i<n;i++) {
445                     r = *s->bytestream++;
446                     g = *s->bytestream++;
447                     b = *s->bytestream++;
448                     s->palette[i] = (0xff << 24) | (r << 16) | (g << 8) | b;
449                 }
450                 for(;i<256;i++) {
451                     s->palette[i] = (0xff << 24);
452                 }
453                 s->state |= PNG_PLTE;
454                 crc = bytestream_get_be32(&s->bytestream);
455             }
456             break;
457         case MKTAG('t', 'R', 'N', 'S'):
458             {
459                 int v, i;
460
461                 /* read the transparency. XXX: Only palette mode supported */
462                 if (s->color_type != PNG_COLOR_TYPE_PALETTE ||
463                     length > 256 ||
464                     !(s->state & PNG_PLTE))
465                     goto skip_tag;
466                 for(i=0;i<length;i++) {
467                     v = *s->bytestream++;
468                     s->palette[i] = (s->palette[i] & 0x00ffffff) | (v << 24);
469                 }
470                 crc = bytestream_get_be32(&s->bytestream);
471             }
472             break;
473         case MKTAG('I', 'E', 'N', 'D'):
474             if (!(s->state & PNG_ALLIMAGE))
475                 goto fail;
476             crc = bytestream_get_be32(&s->bytestream);
477             goto exit_loop;
478         default:
479             /* skip tag */
480         skip_tag:
481             s->bytestream += length + 4;
482             break;
483         }
484     }
485  exit_loop:
486     *picture= *(AVFrame*)&s->picture;
487     *data_size = sizeof(AVPicture);
488
489     ret = s->bytestream - s->bytestream_start;
490  the_end:
491     inflateEnd(&s->zstream);
492     av_freep(&s->crow_buf);
493     av_freep(&s->last_row);
494     av_freep(&s->tmp_row);
495     return ret;
496  fail:
497     ret = -1;
498     goto the_end;
499 }
500
501 AVCodec png_decoder = {
502     "png",
503     CODEC_TYPE_VIDEO,
504     CODEC_ID_PNG,
505     sizeof(PNGContext),
506     ff_png_common_init,
507     NULL,
508     NULL, //decode_end,
509     decode_frame,
510     0 /*CODEC_CAP_DR1*/ /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
511     NULL
512 };