]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/png.c
make state transition tables global as they are constant and the code is slightly...
[ffmpeg] / libavcodec / png.c
index 2945d0cc54bdb0da7a01732973f80df1c3437b0a..0dd9eaec23fce01ecc59640f905df3d6bfbd6d0f 100644 (file)
@@ -2,19 +2,21 @@
  * PNG image format
  * Copyright (c) 2003 Fabrice Bellard.
  *
- * This library is free software; you can redistribute it and/or
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
+ * version 2.1 of the License, or (at your option) any later version.
  *
- * This library is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include "avcodec.h"
 
@@ -69,7 +71,7 @@ typedef struct PNGContext {
     int channels;
     int bits_per_pixel;
     int bpp;
-    
+
     uint8_t *image_buf;
     int image_linesize;
     uint32_t palette[256];
@@ -90,12 +92,14 @@ static unsigned int get32(uint8_t **b){
     return ((*b)[-4]<<24) + ((*b)[-3]<<16) + ((*b)[-2]<<8) + (*b)[-1];
 }
 
+#ifdef CONFIG_ENCODERS
 static void put32(uint8_t **b, unsigned int v){
     *(*b)++= v>>24;
     *(*b)++= v>>16;
     *(*b)++= v>>8;
     *(*b)++= v;
 }
+#endif
 
 static const uint8_t pngsig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
 
@@ -125,7 +129,7 @@ static const uint8_t png_pass_mask[NB_PASSES] = {
 };
 
 /* Mask to determine which pixels to overwrite while displaying */
-static const uint8_t png_pass_dsp_mask[NB_PASSES] = { 
+static const uint8_t png_pass_dsp_mask[NB_PASSES] = {
     0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff
 };
 #if 0
@@ -178,14 +182,14 @@ static int png_pass_row_size(int pass, int bits_per_pixel, int width)
 /* NOTE: we try to construct a good looking image at each pass. width
    is the original image width. We also do pixel format convertion at
    this stage */
-static void png_put_interlaced_row(uint8_t *dst, int width, 
-                                   int bits_per_pixel, int pass, 
+static void png_put_interlaced_row(uint8_t *dst, int width,
+                                   int bits_per_pixel, int pass,
                                    int color_type, const uint8_t *src)
 {
     int x, mask, dsp_mask, j, src_x, b, bpp;
     uint8_t *d;
     const uint8_t *s;
-    
+
     mask = png_pass_mask[pass];
     dsp_mask = png_pass_dsp_mask[pass];
     switch(bits_per_pixel) {
@@ -233,8 +237,9 @@ static void png_put_interlaced_row(uint8_t *dst, int width,
     }
 }
 
-static void png_get_interlaced_row(uint8_t *dst, int row_size, 
-                                   int bits_per_pixel, int pass, 
+#ifdef CONFIG_ENCODERS
+static void png_get_interlaced_row(uint8_t *dst, int row_size,
+                                   int bits_per_pixel, int pass,
                                    const uint8_t *src, int width)
 {
     int x, mask, dst_x, j, b, bpp;
@@ -270,10 +275,11 @@ static void png_get_interlaced_row(uint8_t *dst, int row_size,
         break;
     }
 }
+#endif
 
 /* XXX: optimize */
 /* NOTE: 'dst' can be equal to 'last' */
-static void png_filter_row(uint8_t *dst, int filter_type, 
+static void png_filter_row(uint8_t *dst, int filter_type,
                            uint8_t *src, uint8_t *last, int size, int bpp)
 {
     int i, p;
@@ -338,15 +344,16 @@ static void png_filter_row(uint8_t *dst, int filter_type,
     }
 }
 
+#ifdef CONFIG_ENCODERS
 static void convert_from_rgba32(uint8_t *dst, const uint8_t *src, int width)
 {
     uint8_t *d;
     int j;
     unsigned int v;
-    
+
     d = dst;
     for(j = 0; j < width; j++) {
-        v = ((uint32_t *)src)[j];
+        v = ((const uint32_t *)src)[j];
         d[0] = v >> 16;
         d[1] = v >> 8;
         d[2] = v;
@@ -354,7 +361,9 @@ static void convert_from_rgba32(uint8_t *dst, const uint8_t *src, int width)
         d += 4;
     }
 }
+#endif
 
+#ifdef CONFIG_DECODERS
 static void convert_to_rgba32(uint8_t *dst, const uint8_t *src, int width)
 {
     int j;
@@ -376,12 +385,12 @@ static void png_handle_row(PNGContext *s)
 {
     uint8_t *ptr, *last_row;
     int got_line;
-    
+
     if (!s->interlace_type) {
         ptr = s->image_buf + s->image_linesize * s->y;
         /* need to swap bytes correctly for RGB_ALPHA */
         if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
-            png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1, 
+            png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
                            s->last_row, s->row_size, s->bpp);
             memcpy(s->last_row, s->tmp_row, s->row_size);
             convert_to_rgba32(ptr, s->tmp_row, s->width);
@@ -391,8 +400,8 @@ static void png_handle_row(PNGContext *s)
                 last_row = s->last_row;
             else
                 last_row = ptr - s->image_linesize;
-            
-            png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1, 
+
+            png_filter_row(ptr, s->crow_buf[0], s->crow_buf + 1,
                            last_row, s->row_size, s->bpp);
         }
         s->y++;
@@ -408,14 +417,14 @@ static void png_handle_row(PNGContext *s)
                    wait for the next one */
                 if (got_line)
                     break;
-                png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1, 
+                png_filter_row(s->tmp_row, s->crow_buf[0], s->crow_buf + 1,
                                s->last_row, s->pass_row_size, s->bpp);
                 memcpy(s->last_row, s->tmp_row, s->pass_row_size);
                 got_line = 1;
             }
             if ((png_pass_dsp_ymask[s->pass] << (s->y & 7)) & 0x80) {
                 /* NOTE: rgba32 is handled directly in png_put_interlaced_row */
-                png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass, 
+                png_put_interlaced_row(ptr, s->width, s->bits_per_pixel, s->pass,
                                        s->color_type, s->last_row);
             }
             s->y++;
@@ -427,8 +436,8 @@ static void png_handle_row(PNGContext *s)
                     } else {
                         s->pass++;
                         s->y = 0;
-                        s->pass_row_size = png_pass_row_size(s->pass, 
-                                                             s->bits_per_pixel, 
+                        s->pass_row_size = png_pass_row_size(s->pass,
+                                                             s->bits_per_pixel,
                                                              s->width);
                         s->crow_size = s->pass_row_size + 1;
                         if (s->pass_row_size != 0)
@@ -448,7 +457,7 @@ static int png_decode_idat(PNGContext *s, int length)
     s->zstream.avail_in = length;
     s->zstream.next_in = s->bytestream;
     s->bytestream += length;
-    
+
     if(s->bytestream > s->bytestream_end)
         return -1;
 
@@ -469,7 +478,7 @@ static int png_decode_idat(PNGContext *s, int length)
     return 0;
 }
 
-static int decode_frame(AVCodecContext *avctx, 
+static int decode_frame(AVCodecContext *avctx,
                         void *data, int *data_size,
                         uint8_t *buf, int buf_size)
 {
@@ -479,11 +488,6 @@ static int decode_frame(AVCodecContext *avctx,
     uint32_t tag, length;
     int ret, crc;
 
-    /* special case for last picture */
-    if (buf_size == 0) {
-        return 0;
-    }
-    
     s->bytestream_start=
     s->bytestream= buf;
     s->bytestream_end= buf + buf_size;
@@ -512,7 +516,7 @@ static int decode_frame(AVCodecContext *avctx,
         tag32 = get32(&s->bytestream);
         tag = bswap_32(tag32);
 #ifdef DEBUG
-        printf("png: tag=%c%c%c%c length=%u\n", 
+        av_log(avctx, AV_LOG_DEBUG, "png: tag=%c%c%c%c length=%u\n",
                (tag & 0xff),
                ((tag >> 8) & 0xff),
                ((tag >> 16) & 0xff),
@@ -536,8 +540,8 @@ static int decode_frame(AVCodecContext *avctx,
             crc = get32(&s->bytestream);
             s->state |= PNG_IHDR;
 #ifdef DEBUG
-            printf("width=%d height=%d depth=%d color_type=%d compression_type=%d filter_type=%d interlace_type=%d\n", 
-                   s->width, s->height, s->bit_depth, s->color_type, 
+            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",
+                   s->width, s->height, s->bit_depth, s->color_type,
                    s->compression_type, s->filter_type, s->interlace_type);
 #endif
             break;
@@ -554,16 +558,16 @@ static int decode_frame(AVCodecContext *avctx,
                 s->bpp = (s->bits_per_pixel + 7) >> 3;
                 s->row_size = (avctx->width * s->bits_per_pixel + 7) >> 3;
 
-                if (s->bit_depth == 8 && 
+                if (s->bit_depth == 8 &&
                     s->color_type == PNG_COLOR_TYPE_RGB) {
                     avctx->pix_fmt = PIX_FMT_RGB24;
-                } else if (s->bit_depth == 8 && 
+                } else if (s->bit_depth == 8 &&
                            s->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
                     avctx->pix_fmt = PIX_FMT_RGBA32;
-                } else if (s->bit_depth == 8 && 
+                } else if (s->bit_depth == 8 &&
                            s->color_type == PNG_COLOR_TYPE_GRAY) {
                     avctx->pix_fmt = PIX_FMT_GRAY8;
-                } else if (s->bit_depth == 1 && 
+                } else if (s->bit_depth == 1 &&
                            s->color_type == PNG_COLOR_TYPE_GRAY) {
                     avctx->pix_fmt = PIX_FMT_MONOBLACK;
                 } else if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
@@ -573,7 +577,7 @@ static int decode_frame(AVCodecContext *avctx,
                 }
                 if(p->data[0])
                     avctx->release_buffer(avctx, p);
-            
+
                 p->reference= 0;
                 if(avctx->get_buffer(avctx, p) < 0){
                     av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
@@ -588,13 +592,13 @@ static int decode_frame(AVCodecContext *avctx,
                     s->crow_size = s->row_size + 1;
                 } else {
                     s->pass = 0;
-                    s->pass_row_size = png_pass_row_size(s->pass, 
-                                                         s->bits_per_pixel, 
+                    s->pass_row_size = png_pass_row_size(s->pass,
+                                                         s->bits_per_pixel,
                                                          s->width);
                     s->crow_size = s->pass_row_size + 1;
                 }
 #ifdef DEBUG
-                printf("row_size=%d crow_size =%d\n", 
+                av_log(avctx, AV_LOG_DEBUG, "row_size=%d crow_size =%d\n",
                        s->row_size, s->crow_size);
 #endif
                 s->image_buf = p->data[0];
@@ -628,7 +632,7 @@ static int decode_frame(AVCodecContext *avctx,
         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 */
@@ -689,7 +693,9 @@ static int decode_frame(AVCodecContext *avctx,
     ret = -1;
     goto the_end;
 }
+#endif
 
+#ifdef CONFIG_ENCODERS
 static void png_write_chunk(uint8_t **f, uint32_t tag,
                             const uint8_t *buf, int length)
 {
@@ -741,6 +747,7 @@ static int png_write_row(PNGContext *s, const uint8_t *data, int size)
     }
     return 0;
 }
+#endif /* CONFIG_ENCODERS */
 
 static int common_init(AVCodecContext *avctx){
     PNGContext *s = avctx->priv_data;
@@ -752,6 +759,7 @@ static int common_init(AVCodecContext *avctx){
     return 0;
 }
 
+#ifdef CONFIG_ENCODERS
 static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
     PNGContext *s = avctx->priv_data;
     AVFrame *pict = data;
@@ -765,7 +773,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
     *p = *pict;
     p->pict_type= FF_I_TYPE;
     p->key_frame= 1;
-    
+
     s->bytestream_start=
     s->bytestream= buf;
     s->bytestream_end= buf+buf_size;
@@ -817,7 +825,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
     /* write png header */
     memcpy(s->bytestream, pngsig, 8);
     s->bytestream += 8;
-    
+
     to_be32(s->buf, avctx->width);
     to_be32(s->buf + 4, avctx->height);
     s->buf[8] = bit_depth;
@@ -825,7 +833,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
     s->buf[10] = 0; /* compression type */
     s->buf[11] = 0; /* filter type */
     s->buf[12] = is_progressive; /* interlace type */
-    
+
     png_write_chunk(&s->bytestream, MKTAG('I', 'H', 'D', 'R'), s->buf, 13);
 
     /* put the palette if needed */
@@ -834,7 +842,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
         unsigned int v;
         uint32_t *palette;
         uint8_t *alpha_ptr;
-        
+
         palette = (uint32_t *)p->data[1];
         ptr = s->buf;
         alpha_ptr = s->buf + 256 * 3;
@@ -877,8 +885,8 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
                         } else {
                             ptr1 = ptr;
                         }
-                        png_get_interlaced_row(crow_buf + 1, pass_row_size, 
-                                               bits_per_pixel, pass, 
+                        png_get_interlaced_row(crow_buf + 1, pass_row_size,
+                                               bits_per_pixel, pass,
                                                ptr1, avctx->width);
                         crow_buf[0] = PNG_FILTER_VALUE_NONE;
                         png_write_row(s, crow_buf, pass_row_size + 1);
@@ -925,7 +933,9 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
     ret = -1;
     goto the_end;
 }
+#endif
 
+#ifdef CONFIG_PNG_DECODER
 AVCodec png_decoder = {
     "png",
     CODEC_TYPE_VIDEO,
@@ -938,7 +948,9 @@ AVCodec png_decoder = {
     0 /*CODEC_CAP_DR1*/ /*| CODEC_CAP_DRAW_HORIZ_BAND*/,
     NULL
 };
+#endif
 
+#ifdef CONFIG_PNG_ENCODER
 AVCodec png_encoder = {
     "png",
     CODEC_TYPE_VIDEO,
@@ -949,4 +961,5 @@ AVCodec png_encoder = {
     NULL, //encode_end,
     .pix_fmts= (enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA32, PIX_FMT_PAL8, PIX_FMT_GRAY8, PIX_FMT_MONOBLACK, -1},
 };
+#endif // CONFIG_PNG_ENCODER
 #endif