diff options
author | Carl Eugen Hoyos <ceffmpeg@gmail.com> | 2019-03-20 17:50:25 +0100 |
---|---|---|
committer | Carl Eugen Hoyos <ceffmpeg@gmail.com> | 2019-03-20 17:50:25 +0100 |
commit | 82fd7866a3d7045c1cbd8f47651410baa001f447 (patch) | |
tree | d62bdd203cc5b40d9655b08fdece89607bad62b3 | |
parent | 7be245498b1d0a1b11cebad6a3a0a4ab0e9a846a (diff) | |
download | ffmpeg-82fd7866a3d7045c1cbd8f47651410baa001f447.tar.gz |
lavc/tiff: Allow decoding of cmyka (five components).
Fixes ticket #7675.
-rw-r--r-- | libavcodec/tiff.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 828ed9e2e9..29a80a6892 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -827,6 +827,10 @@ static int init_image(TiffContext *s, ThreadFrame *frame) case 324: s->avctx->pix_fmt = s->photometric == TIFF_PHOTOMETRIC_SEPARATED ? AV_PIX_FMT_RGB0 : AV_PIX_FMT_RGBA; break; + case 405: + if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED) + s->avctx->pix_fmt = AV_PIX_FMT_RGBA; + break; case 483: s->avctx->pix_fmt = s->le ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB48BE; break; @@ -944,7 +948,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) s->height = value; break; case TIFF_BPP: - if (count > 4U) { + if (count > 5U) { av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%d, %d components)\n", value, count); @@ -975,7 +979,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) "Samples per pixel requires a single value, many provided\n"); return AVERROR_INVALIDDATA; } - if (value > 4U) { + if (value > 5U) { av_log(s->avctx, AV_LOG_ERROR, "Samples per pixel %d is too large\n", value); return AVERROR_INVALIDDATA; @@ -1449,10 +1453,19 @@ again: planes = s->planar ? s->bppcount : 1; for (plane = 0; plane < planes; plane++) { + uint8_t *five_planes = NULL; int remaining = avpkt->size; int decoded_height; stride = p->linesize[plane]; dst = p->data[plane]; + if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED && + s->avctx->pix_fmt == AV_PIX_FMT_RGBA) { + stride = stride * 5 / 4; + five_planes = + dst = av_malloc(stride * s->height); + if (!dst) + return AVERROR(ENOMEM); + } for (i = 0; i < s->height; i += s->rps) { if (i) dst += s->rps * stride; @@ -1468,13 +1481,16 @@ again: if (soff > avpkt->size || ssize > avpkt->size - soff || ssize > remaining) { av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n"); + av_freep(&five_planes); return AVERROR_INVALIDDATA; } remaining -= ssize; if ((ret = tiff_unpack_strip(s, p, dst, stride, avpkt->data + soff, ssize, i, FFMIN(s->rps, s->height - i))) < 0) { - if (avctx->err_recognition & AV_EF_EXPLODE) + if (avctx->err_recognition & AV_EF_EXPLODE) { + av_freep(&five_planes); return ret; + } break; } } @@ -1485,7 +1501,7 @@ again: av_log(s->avctx, AV_LOG_ERROR, "predictor == 2 with YUV is unsupported"); return AVERROR_PATCHWELCOME; } - dst = p->data[plane]; + dst = five_planes ? five_planes : p->data[plane]; soff = s->bpp >> 3; if (s->planar) soff = FFMAX(soff / s->bppcount, 1); @@ -1532,21 +1548,25 @@ again: } if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED && - s->avctx->pix_fmt == AV_PIX_FMT_RGB0) { + (s->avctx->pix_fmt == AV_PIX_FMT_RGB0 || s->avctx->pix_fmt == AV_PIX_FMT_RGBA)) { + int x = s->avctx->pix_fmt == AV_PIX_FMT_RGB0 ? 4 : 5; + uint8_t *src = five_planes ? five_planes : p->data[plane]; dst = p->data[plane]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) { - int k = 255 - dst[4 * j + 3]; - int r = (255 - dst[4 * j ]) * k; - int g = (255 - dst[4 * j + 1]) * k; - int b = (255 - dst[4 * j + 2]) * k; + int k = 255 - src[x * j + 3]; + int r = (255 - src[x * j ]) * k; + int g = (255 - src[x * j + 1]) * k; + int b = (255 - src[x * j + 2]) * k; dst[4 * j ] = r * 257 >> 16; dst[4 * j + 1] = g * 257 >> 16; dst[4 * j + 2] = b * 257 >> 16; - dst[4 * j + 3] = 255; + dst[4 * j + 3] = s->avctx->pix_fmt == AV_PIX_FMT_RGBA ? src[x * j + 4] : 255; } + src += stride; dst += p->linesize[plane]; } + av_freep(&five_planes); } else if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED && s->avctx->pix_fmt == AV_PIX_FMT_RGBA64BE) { dst = p->data[plane]; |