avcodec/pngdec: support alpha blending for palette apng

Update clock test, as PAL8 apngs are now decoded as RGBA.
This commit is contained in:
Paul B Mahol 2022-03-05 18:36:43 +01:00
parent 1bed27acef
commit a0fc6c4a8e
2 changed files with 72 additions and 69 deletions

View File

@ -677,7 +677,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
avctx->pix_fmt = AV_PIX_FMT_RGBA64BE;
} else if ((s->bits_per_pixel == 1 || s->bits_per_pixel == 2 || s->bits_per_pixel == 4 || s->bits_per_pixel == 8) &&
s->color_type == PNG_COLOR_TYPE_PALETTE) {
avctx->pix_fmt = AV_PIX_FMT_PAL8;
avctx->pix_fmt = avctx->codec_id == AV_CODEC_ID_APNG ? AV_PIX_FMT_RGBA : AV_PIX_FMT_PAL8;
} else if (s->bit_depth == 1 && s->bits_per_pixel == 1 && avctx->codec_id != AV_CODEC_ID_APNG) {
avctx->pix_fmt = AV_PIX_FMT_MONOBLACK;
} else if (s->bit_depth == 8 &&
@ -1022,7 +1022,6 @@ static int decode_fctl_chunk(AVCodecContext *avctx, PNGDecContext *s,
if (blend_op == APNG_BLEND_OP_OVER && !s->has_trns && (
avctx->pix_fmt == AV_PIX_FMT_RGB24 ||
avctx->pix_fmt == AV_PIX_FMT_RGB48BE ||
avctx->pix_fmt == AV_PIX_FMT_PAL8 ||
avctx->pix_fmt == AV_PIX_FMT_GRAY8 ||
avctx->pix_fmt == AV_PIX_FMT_GRAY16BE ||
avctx->pix_fmt == AV_PIX_FMT_MONOBLACK
@ -1070,13 +1069,13 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
ptrdiff_t dst_stride = p->linesize[0];
const uint8_t *src = s->last_picture.f->data[0];
ptrdiff_t src_stride = s->last_picture.f->linesize[0];
const int bpp = s->color_type == PNG_COLOR_TYPE_PALETTE ? 4 : s->bpp;
size_t x, y;
if (s->blend_op == APNG_BLEND_OP_OVER &&
avctx->pix_fmt != AV_PIX_FMT_RGBA &&
avctx->pix_fmt != AV_PIX_FMT_GRAY8A &&
avctx->pix_fmt != AV_PIX_FMT_PAL8) {
avctx->pix_fmt != AV_PIX_FMT_GRAY8A) {
avpriv_request_sample(avctx, "Blending with pixel format %s",
av_get_pix_fmt_name(avctx->pix_fmt));
return AVERROR_PATCHWELCOME;
@ -1095,7 +1094,7 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; y++) {
memset(s->background_buf + src_stride * y +
s->bpp * s->last_x_offset, 0, s->bpp * s->last_w);
bpp * s->last_x_offset, 0, bpp * s->last_w);
}
src = s->background_buf;
@ -1103,22 +1102,22 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
// copy unchanged rectangles from the last frame
for (y = 0; y < s->y_offset; y++)
memcpy(dst + y * dst_stride, src + y * src_stride, p->width * s->bpp);
memcpy(dst + y * dst_stride, src + y * src_stride, p->width * bpp);
for (y = s->y_offset; y < s->y_offset + s->cur_h; y++) {
memcpy(dst + y * dst_stride, src + y * src_stride, s->x_offset * s->bpp);
memcpy(dst + y * dst_stride + (s->x_offset + s->cur_w) * s->bpp,
src + y * src_stride + (s->x_offset + s->cur_w) * s->bpp,
(p->width - s->cur_w - s->x_offset) * s->bpp);
memcpy(dst + y * dst_stride, src + y * src_stride, s->x_offset * bpp);
memcpy(dst + y * dst_stride + (s->x_offset + s->cur_w) * bpp,
src + y * src_stride + (s->x_offset + s->cur_w) * bpp,
(p->width - s->cur_w - s->x_offset) * bpp);
}
for (y = s->y_offset + s->cur_h; y < p->height; y++)
memcpy(dst + y * dst_stride, src + y * src_stride, p->width * s->bpp);
memcpy(dst + y * dst_stride, src + y * src_stride, p->width * bpp);
if (s->blend_op == APNG_BLEND_OP_OVER) {
// Perform blending
for (y = s->y_offset; y < s->y_offset + s->cur_h; ++y) {
uint8_t *foreground = dst + dst_stride * y + s->bpp * s->x_offset;
const uint8_t *background = src + src_stride * y + s->bpp * s->x_offset;
for (x = s->x_offset; x < s->x_offset + s->cur_w; ++x, foreground += s->bpp, background += s->bpp) {
uint8_t *foreground = dst + dst_stride * y + bpp * s->x_offset;
const uint8_t *background = src + src_stride * y + bpp * s->x_offset;
for (x = s->x_offset; x < s->x_offset + s->cur_w; ++x, foreground += bpp, background += bpp) {
size_t b;
uint8_t foreground_alpha, background_alpha, output_alpha;
uint8_t output[10];
@ -1137,32 +1136,21 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
foreground_alpha = foreground[1];
background_alpha = background[1];
break;
case AV_PIX_FMT_PAL8:
foreground_alpha = s->palette[foreground[0]] >> 24;
background_alpha = s->palette[background[0]] >> 24;
break;
}
if (foreground_alpha == 255)
continue;
if (foreground_alpha == 0) {
memcpy(foreground, background, s->bpp);
continue;
}
if (avctx->pix_fmt == AV_PIX_FMT_PAL8) {
// TODO: Alpha blending with PAL8 will likely need the entire image converted over to RGBA first
avpriv_request_sample(avctx, "Alpha blending palette samples");
memcpy(foreground, background, bpp);
continue;
}
output_alpha = foreground_alpha + FAST_DIV255((255 - foreground_alpha) * background_alpha);
av_assert0(s->bpp <= 10);
av_assert0(bpp <= 10);
for (b = 0; b < s->bpp - 1; ++b) {
for (b = 0; b < bpp - 1; ++b) {
if (output_alpha == 0) {
output[b] = 0;
} else if (background_alpha == 255) {
@ -1172,7 +1160,7 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
}
}
output[b] = output_alpha;
memcpy(foreground, output, s->bpp);
memcpy(foreground, output, bpp);
}
}
}
@ -1368,6 +1356,21 @@ exit_loop:
if (s->bits_per_pixel <= 4)
handle_small_bpp(s, p);
if (s->color_type == PNG_COLOR_TYPE_PALETTE && avctx->codec_id == AV_CODEC_ID_APNG) {
for (int y = 0; y < s->height; y++) {
uint8_t *row = &p->data[0][p->linesize[0] * y];
for (int x = s->width - 1; x >= 0; x--) {
const uint8_t idx = row[x];
row[4*x+2] = s->palette[idx] & 0xFF;
row[4*x+1] = (s->palette[idx] >> 8 ) & 0xFF;
row[4*x+0] = (s->palette[idx] >> 16) & 0xFF;
row[4*x+3] = s->palette[idx] >> 24;
}
}
}
/* apply transparency if needed */
if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE) {
size_t byte_depth = s->bit_depth > 8 ? 2 : 1;

View File

@ -3,43 +3,43 @@
#codec_id 0: rawvideo
#dimensions 0: 150x150
#sar 0: 0/1
0, 0, 0, 1, 23524, 0xf09caaa1
0, 1, 1, 1, 23524, 0x1a329f21
0, 2, 2, 1, 23524, 0x9b0ca017
0, 3, 3, 1, 23524, 0x73b09deb
0, 4, 4, 1, 23524, 0x23039f49
0, 5, 5, 1, 23524, 0x58869e7b
0, 6, 6, 1, 23524, 0xc26397d2
0, 7, 7, 1, 23524, 0xe07f7d87
0, 8, 8, 1, 23524, 0x619a82ba
0, 9, 9, 1, 23524, 0x696c9757
0, 10, 10, 1, 23524, 0x7303a4a6
0, 11, 11, 1, 23524, 0x1e149aee
0, 12, 12, 1, 23524, 0x78dd97e0
0, 13, 13, 1, 23524, 0xad8092d3
0, 14, 14, 1, 23524, 0x27c090b4
0, 15, 15, 1, 23524, 0x904c97be
0, 16, 16, 1, 23524, 0x54d29b9e
0, 17, 17, 1, 23524, 0x57689bfa
0, 18, 18, 1, 23524, 0x2772a00e
0, 19, 19, 1, 23524, 0x6a769ef6
0, 20, 20, 1, 23524, 0x94d8aad5
0, 21, 21, 1, 23524, 0x52f79ec4
0, 22, 22, 1, 23524, 0x99ee9fbc
0, 23, 23, 1, 23524, 0xbd6a9e4d
0, 24, 24, 1, 23524, 0xaf4aa1cf
0, 25, 25, 1, 23524, 0xdb929f98
0, 26, 26, 1, 23524, 0x9e189a6f
0, 27, 27, 1, 23524, 0x3ffb9410
0, 28, 28, 1, 23524, 0x6fc9917d
0, 29, 29, 1, 23524, 0xe43e94ca
0, 30, 30, 1, 23524, 0x03b6a24f
0, 31, 31, 1, 23524, 0xc54f99b3
0, 32, 32, 1, 23524, 0x4b9a9748
0, 33, 33, 1, 23524, 0x25a19003
0, 34, 34, 1, 23524, 0x2b9d77cc
0, 35, 35, 1, 23524, 0x4a5a9217
0, 36, 36, 1, 23524, 0x241b9a7c
0, 37, 37, 1, 23524, 0xc9d39b38
0, 38, 38, 1, 23524, 0xcca69f30
0, 39, 39, 1, 23524, 0xe50f9ec9
0, 0, 0, 1, 90000, 0x11af5588
0, 1, 1, 1, 90000, 0x528c2eb8
0, 2, 2, 1, 90000, 0xebae2d82
0, 3, 3, 1, 90000, 0xf57951ef
0, 4, 4, 1, 90000, 0xc2a84734
0, 5, 5, 1, 90000, 0x2dd74265
0, 6, 6, 1, 90000, 0x5a6980cb
0, 7, 7, 1, 90000, 0x519373e4
0, 8, 8, 1, 90000, 0xdca835fb
0, 9, 9, 1, 90000, 0xc8a46d5e
0, 10, 10, 1, 90000, 0xa01a72e3
0, 11, 11, 1, 90000, 0xacd751fa
0, 12, 12, 1, 90000, 0x464b6d39
0, 13, 13, 1, 90000, 0x56f1b22c
0, 14, 14, 1, 90000, 0x0595a6bb
0, 15, 15, 1, 90000, 0xb9418cdc
0, 16, 16, 1, 90000, 0x8b2b7bcf
0, 17, 17, 1, 90000, 0x1a026aaf
0, 18, 18, 1, 90000, 0x25443715
0, 19, 19, 1, 90000, 0x3d9231cd
0, 20, 20, 1, 90000, 0xfef153a8
0, 21, 21, 1, 90000, 0x6a7c2e7b
0, 22, 22, 1, 90000, 0x1fe92cda
0, 23, 23, 1, 90000, 0x30554ff8
0, 24, 24, 1, 90000, 0x57e544d9
0, 25, 25, 1, 90000, 0x4c2d3b69
0, 26, 26, 1, 90000, 0x22c26e0c
0, 27, 27, 1, 90000, 0x254bb498
0, 28, 28, 1, 90000, 0xcd02a4ac
0, 29, 29, 1, 90000, 0x54447feb
0, 30, 30, 1, 90000, 0x9dc87b6e
0, 31, 31, 1, 90000, 0xfb49553b
0, 32, 32, 1, 90000, 0x05316fbe
0, 33, 33, 1, 90000, 0xd796da15
0, 34, 34, 1, 90000, 0x36064111
0, 35, 35, 1, 90000, 0x470cb58e
0, 36, 36, 1, 90000, 0xf0ba8054
0, 37, 37, 1, 90000, 0x3f496ff8
0, 38, 38, 1, 90000, 0xe3a43cff
0, 39, 39, 1, 90000, 0xacdd36ce