diff options
author | Benoit Fouet <benoit.fouet@free.fr> | 2014-11-14 10:17:38 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-11-14 17:13:08 +0100 |
commit | 8cab24df0780ccd8acf5f9e9554b2be9459e8be2 (patch) | |
tree | 18bdfc1a91807397ace504baabaa95c3dab548b0 | |
parent | 24ca2ffad826cb660aa53a25cc35b2a2702ace0e (diff) | |
download | ffmpeg-8cab24df0780ccd8acf5f9e9554b2be9459e8be2.tar.gz |
avcodec/pngdec: create a function to handle small (<=4) bits per pixel values.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavcodec/pngdec.c | 144 |
1 files changed, 75 insertions, 69 deletions
diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 2f22ade6d5..d3c8ef93a1 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]) { |