[FFmpeg-devel] [PATCH 09/10] avcodec/pngdec: create a function to handle small (<=4) bits per pixel values.

Benoit Fouet benoit.fouet at free.fr
Fri Nov 14 10:17:38 CET 2014


---
 libavcodec/pngdec.c | 144 +++++++++++++++++++++++++++-------------------------
 1 file changed, 75 insertions(+), 69 deletions(-)

diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index 2f22ade..d3c8ef9 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -713,6 +713,79 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
     return 0;
 }
 
+static void handle_small_bpp(PNGDecContext *s, AVFrame *p)
+{
+    if (s->bits_per_pixel == 1 && s->color_type == PNG_COLOR_TYPE_PALETTE) {
+        int i, j, k;
+        uint8_t *pd = p->data[0];
+        for (j = 0; j < s->height; j++) {
+            i = s->width / 8;
+            for (k = 7; k >= 1; k--)
+                if ((s->width&7) >= k)
+                    pd[8*i + k - 1] = (pd[i]>>8-k) & 1;
+            for (i--; i >= 0; i--) {
+                pd[8*i + 7]=  pd[i]     & 1;
+                pd[8*i + 6]= (pd[i]>>1) & 1;
+                pd[8*i + 5]= (pd[i]>>2) & 1;
+                pd[8*i + 4]= (pd[i]>>3) & 1;
+                pd[8*i + 3]= (pd[i]>>4) & 1;
+                pd[8*i + 2]= (pd[i]>>5) & 1;
+                pd[8*i + 1]= (pd[i]>>6) & 1;
+                pd[8*i + 0]=  pd[i]>>7;
+            }
+            pd += s->image_linesize;
+        }
+    } else if (s->bits_per_pixel == 2) {
+        int i, j;
+        uint8_t *pd = p->data[0];
+        for (j = 0; j < s->height; j++) {
+            i = s->width / 4;
+            if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
+                if ((s->width&3) >= 3) pd[4*i + 2]= (pd[i] >> 2) & 3;
+                if ((s->width&3) >= 2) pd[4*i + 1]= (pd[i] >> 4) & 3;
+                if ((s->width&3) >= 1) pd[4*i + 0]=  pd[i] >> 6;
+                for (i--; i >= 0; i--) {
+                    pd[4*i + 3]=  pd[i]     & 3;
+                    pd[4*i + 2]= (pd[i]>>2) & 3;
+                    pd[4*i + 1]= (pd[i]>>4) & 3;
+                    pd[4*i + 0]=  pd[i]>>6;
+                }
+            } else {
+                if ((s->width&3) >= 3) pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55;
+                if ((s->width&3) >= 2) pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55;
+                if ((s->width&3) >= 1) pd[4*i + 0]= ( pd[i]>>6     )*0x55;
+                for (i--; i >= 0; i--) {
+                    pd[4*i + 3]= ( pd[i]     & 3)*0x55;
+                    pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55;
+                    pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55;
+                    pd[4*i + 0]= ( pd[i]>>6     )*0x55;
+                }
+            }
+            pd += s->image_linesize;
+        }
+    } else if (s->bits_per_pixel == 4) {
+        int i, j;
+        uint8_t *pd = p->data[0];
+        for (j = 0; j < s->height; j++) {
+            i = s->width/2;
+            if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
+                if (s->width&1) pd[2*i+0]= pd[i]>>4;
+                for (i--; i >= 0; i--) {
+                    pd[2*i + 1] = pd[i] & 15;
+                    pd[2*i + 0] = pd[i] >> 4;
+                }
+            } else {
+                if (s->width & 1) pd[2*i + 0]= (pd[i] >> 4) * 0x11;
+                for (i--; i >= 0; i--) {
+                    pd[2*i + 1] = (pd[i] & 15) * 0x11;
+                    pd[2*i + 0] = (pd[i] >> 4) * 0x11;
+                }
+            }
+            pd += s->image_linesize;
+        }
+    }
+}
+
 static int decode_frame_png(AVCodecContext *avctx,
                         void *data, int *got_frame,
                         AVPacket *avpkt)
@@ -820,75 +893,8 @@ skip_tag:
     }
 exit_loop:
 
-    if (s->bits_per_pixel == 1 && s->color_type == PNG_COLOR_TYPE_PALETTE) {
-        int i, j, k;
-        uint8_t *pd = p->data[0];
-        for (j = 0; j < s->height; j++) {
-            i = s->width / 8;
-            for (k = 7; k >= 1; k--)
-                if ((s->width&7) >= k)
-                    pd[8*i + k - 1] = (pd[i]>>8-k) & 1;
-            for (i--; i >= 0; i--) {
-                pd[8*i + 7]=  pd[i]     & 1;
-                pd[8*i + 6]= (pd[i]>>1) & 1;
-                pd[8*i + 5]= (pd[i]>>2) & 1;
-                pd[8*i + 4]= (pd[i]>>3) & 1;
-                pd[8*i + 3]= (pd[i]>>4) & 1;
-                pd[8*i + 2]= (pd[i]>>5) & 1;
-                pd[8*i + 1]= (pd[i]>>6) & 1;
-                pd[8*i + 0]=  pd[i]>>7;
-            }
-            pd += s->image_linesize;
-        }
-    } else if (s->bits_per_pixel == 2) {
-        int i, j;
-        uint8_t *pd = p->data[0];
-        for (j = 0; j < s->height; j++) {
-            i = s->width / 4;
-            if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
-                if ((s->width&3) >= 3) pd[4*i + 2]= (pd[i] >> 2) & 3;
-                if ((s->width&3) >= 2) pd[4*i + 1]= (pd[i] >> 4) & 3;
-                if ((s->width&3) >= 1) pd[4*i + 0]=  pd[i] >> 6;
-                for (i--; i >= 0; i--) {
-                    pd[4*i + 3]=  pd[i]     & 3;
-                    pd[4*i + 2]= (pd[i]>>2) & 3;
-                    pd[4*i + 1]= (pd[i]>>4) & 3;
-                    pd[4*i + 0]=  pd[i]>>6;
-                }
-            } else {
-                if ((s->width&3) >= 3) pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55;
-                if ((s->width&3) >= 2) pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55;
-                if ((s->width&3) >= 1) pd[4*i + 0]= ( pd[i]>>6     )*0x55;
-                for (i--; i >= 0; i--) {
-                    pd[4*i + 3]= ( pd[i]     & 3)*0x55;
-                    pd[4*i + 2]= ((pd[i]>>2) & 3)*0x55;
-                    pd[4*i + 1]= ((pd[i]>>4) & 3)*0x55;
-                    pd[4*i + 0]= ( pd[i]>>6     )*0x55;
-                }
-            }
-            pd += s->image_linesize;
-        }
-    } else if (s->bits_per_pixel == 4) {
-        int i, j;
-        uint8_t *pd = p->data[0];
-        for (j = 0; j < s->height; j++) {
-            i = s->width/2;
-            if (s->color_type == PNG_COLOR_TYPE_PALETTE) {
-                if (s->width&1) pd[2*i+0]= pd[i]>>4;
-                for (i--; i >= 0; i--) {
-                    pd[2*i + 1] = pd[i] & 15;
-                    pd[2*i + 0] = pd[i] >> 4;
-                }
-            } else {
-                if (s->width & 1) pd[2*i + 0]= (pd[i] >> 4) * 0x11;
-                for (i--; i >= 0; i--) {
-                    pd[2*i + 1] = (pd[i] & 15) * 0x11;
-                    pd[2*i + 0] = (pd[i] >> 4) * 0x11;
-                }
-            }
-            pd += s->image_linesize;
-        }
-    }
+    if (s->bits_per_pixel <= 4)
+        handle_small_bpp(s, p);
 
     /* handle p-frames only if a predecessor frame is available */
     if (s->last_picture.f->data[0]) {
-- 
2.2.0.rc1.23.gf570943



More information about the ffmpeg-devel mailing list