mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-29 22:00:58 +02:00
avcodec/pngdec: create a function to handle small (<=4) bits per pixel values.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
24ca2ffad8
commit
8cab24df07
@ -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]) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user