Commit 82fd7866 authored by Carl Eugen Hoyos's avatar Carl Eugen Hoyos

lavc/tiff: Allow decoding of cmyka (five components).

Fixes ticket #7675.
parent 7be24549
...@@ -827,6 +827,10 @@ static int init_image(TiffContext *s, ThreadFrame *frame) ...@@ -827,6 +827,10 @@ static int init_image(TiffContext *s, ThreadFrame *frame)
case 324: case 324:
s->avctx->pix_fmt = s->photometric == TIFF_PHOTOMETRIC_SEPARATED ? AV_PIX_FMT_RGB0 : AV_PIX_FMT_RGBA; s->avctx->pix_fmt = s->photometric == TIFF_PHOTOMETRIC_SEPARATED ? AV_PIX_FMT_RGB0 : AV_PIX_FMT_RGBA;
break; break;
case 405:
if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED)
s->avctx->pix_fmt = AV_PIX_FMT_RGBA;
break;
case 483: case 483:
s->avctx->pix_fmt = s->le ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB48BE; s->avctx->pix_fmt = s->le ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB48BE;
break; break;
...@@ -944,7 +948,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) ...@@ -944,7 +948,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame)
s->height = value; s->height = value;
break; break;
case TIFF_BPP: case TIFF_BPP:
if (count > 4U) { if (count > 5U) {
av_log(s->avctx, AV_LOG_ERROR, av_log(s->avctx, AV_LOG_ERROR,
"This format is not supported (bpp=%d, %d components)\n", "This format is not supported (bpp=%d, %d components)\n",
value, count); value, count);
...@@ -975,7 +979,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) ...@@ -975,7 +979,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame)
"Samples per pixel requires a single value, many provided\n"); "Samples per pixel requires a single value, many provided\n");
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
if (value > 4U) { if (value > 5U) {
av_log(s->avctx, AV_LOG_ERROR, av_log(s->avctx, AV_LOG_ERROR,
"Samples per pixel %d is too large\n", value); "Samples per pixel %d is too large\n", value);
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
...@@ -1449,10 +1453,19 @@ again: ...@@ -1449,10 +1453,19 @@ again:
planes = s->planar ? s->bppcount : 1; planes = s->planar ? s->bppcount : 1;
for (plane = 0; plane < planes; plane++) { for (plane = 0; plane < planes; plane++) {
uint8_t *five_planes = NULL;
int remaining = avpkt->size; int remaining = avpkt->size;
int decoded_height; int decoded_height;
stride = p->linesize[plane]; stride = p->linesize[plane];
dst = p->data[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) { for (i = 0; i < s->height; i += s->rps) {
if (i) if (i)
dst += s->rps * stride; dst += s->rps * stride;
...@@ -1468,13 +1481,16 @@ again: ...@@ -1468,13 +1481,16 @@ again:
if (soff > avpkt->size || ssize > avpkt->size - soff || ssize > remaining) { if (soff > avpkt->size || ssize > avpkt->size - soff || ssize > remaining) {
av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n"); av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n");
av_freep(&five_planes);
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
} }
remaining -= ssize; remaining -= ssize;
if ((ret = tiff_unpack_strip(s, p, dst, stride, avpkt->data + soff, ssize, i, if ((ret = tiff_unpack_strip(s, p, dst, stride, avpkt->data + soff, ssize, i,
FFMIN(s->rps, s->height - i))) < 0) { 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; return ret;
}
break; break;
} }
} }
...@@ -1485,7 +1501,7 @@ again: ...@@ -1485,7 +1501,7 @@ again:
av_log(s->avctx, AV_LOG_ERROR, "predictor == 2 with YUV is unsupported"); av_log(s->avctx, AV_LOG_ERROR, "predictor == 2 with YUV is unsupported");
return AVERROR_PATCHWELCOME; return AVERROR_PATCHWELCOME;
} }
dst = p->data[plane]; dst = five_planes ? five_planes : p->data[plane];
soff = s->bpp >> 3; soff = s->bpp >> 3;
if (s->planar) if (s->planar)
soff = FFMAX(soff / s->bppcount, 1); soff = FFMAX(soff / s->bppcount, 1);
...@@ -1532,21 +1548,25 @@ again: ...@@ -1532,21 +1548,25 @@ again:
} }
if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED && 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]; dst = p->data[plane];
for (i = 0; i < s->height; i++) { for (i = 0; i < s->height; i++) {
for (j = 0; j < s->width; j++) { for (j = 0; j < s->width; j++) {
int k = 255 - dst[4 * j + 3]; int k = 255 - src[x * j + 3];
int r = (255 - dst[4 * j ]) * k; int r = (255 - src[x * j ]) * k;
int g = (255 - dst[4 * j + 1]) * k; int g = (255 - src[x * j + 1]) * k;
int b = (255 - dst[4 * j + 2]) * k; int b = (255 - src[x * j + 2]) * k;
dst[4 * j ] = r * 257 >> 16; dst[4 * j ] = r * 257 >> 16;
dst[4 * j + 1] = g * 257 >> 16; dst[4 * j + 1] = g * 257 >> 16;
dst[4 * j + 2] = b * 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]; dst += p->linesize[plane];
} }
av_freep(&five_planes);
} else if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED && } else if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED &&
s->avctx->pix_fmt == AV_PIX_FMT_RGBA64BE) { s->avctx->pix_fmt == AV_PIX_FMT_RGBA64BE) {
dst = p->data[plane]; dst = p->data[plane];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment