diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 42cead7e34..0ad12a12a7 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -52,6 +52,7 @@ typedef struct TiffContext { int le; enum TiffCompr compr; int invert; + int planar; int fax_opts; int predictor; int fill_order; @@ -431,6 +432,9 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride, const uint8_t *ssrc = src; int width = ((s->width * s->bpp) + 7) >> 3; + if (s->planar) + width /= s->bppcount; + if (size <= 0) return AVERROR_INVALIDDATA; @@ -617,22 +621,24 @@ static int init_image(TiffContext *s, AVFrame *frame) s->avctx->pix_fmt = AV_PIX_FMT_PAL8; break; case 243: - s->avctx->pix_fmt = AV_PIX_FMT_RGB24; + s->avctx->pix_fmt = s->planar ? AV_PIX_FMT_GBRP : AV_PIX_FMT_RGB24; break; case 161: s->avctx->pix_fmt = s->le ? AV_PIX_FMT_GRAY16LE : AV_PIX_FMT_GRAY16BE; break; case 162: - s->avctx->pix_fmt = AV_PIX_FMT_GRAY8A; + s->avctx->pix_fmt = s>planar ? AV_PIX_FMT_NONE : AV_PIX_FMT_GRAY8A; break; case 324: - s->avctx->pix_fmt = AV_PIX_FMT_RGBA; + s->avctx->pix_fmt = s->planar ? AV_PIX_FMT_GBRAP : AV_PIX_FMT_RGBA; break; case 483: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB48BE; + s->avctx->pix_fmt = s->planar ? (s->le ? AV_PIX_FMT_GBRP16LE : AV_PIX_FMT_GBRP16BE) : + (s->le ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB48BE); break; case 644: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_RGBA64LE : AV_PIX_FMT_RGBA64BE; + s->avctx->pix_fmt = s->planar ? (s->le ? AV_PIX_FMT_GBRAP16LE : AV_PIX_FMT_GBRAP16BE) : + (s->le ? AV_PIX_FMT_RGBA64LE : AV_PIX_FMT_RGBA64BE); break; default: av_log(s->avctx, AV_LOG_ERROR, @@ -884,10 +890,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) s->palette_is_set = 1; break; case TIFF_PLANAR: - if (value == 2) { - av_log(s->avctx, AV_LOG_ERROR, "Planar format is not supported\n"); - return AVERROR_PATCHWELCOME; - } + s->planar = value == 2; break; case TIFF_T4OPTIONS: if (s->compr == TIFF_G3) @@ -1042,7 +1045,7 @@ static int decode_frame(AVCodecContext *avctx, TiffContext *const s = avctx->priv_data; AVFrame *const p = data; unsigned off; - int id, le, ret; + int id, le, ret, plane, planes; int i, j, entries; int stride; unsigned soff, ssize; @@ -1125,8 +1128,6 @@ static int decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); s->stripsize = avpkt->size - s->stripoff; } - stride = p->linesize[0]; - dst = p->data[0]; if (s->stripsizesoff) { if (s->stripsizesoff >= (unsigned)avpkt->size) @@ -1144,6 +1145,10 @@ static int decode_frame(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } + planes = s->planar ? s->bppcount : 1; + for (plane = 0; plane < planes; plane++) { + stride = p->linesize[plane]; + dst = p->data[plane]; for (i = 0; i < s->height; i += s->rps) { if (s->stripsizesoff) ssize = tget(&stripsizes, s->sstype, s->le); @@ -1165,7 +1170,7 @@ static int decode_frame(AVCodecContext *avctx, dst += s->rps * stride; } if (s->predictor == 2) { - dst = p->data[0]; + dst = p->data[plane]; soff = s->bpp >> 3; ssize = s->width * soff; if (s->avctx->pix_fmt == AV_PIX_FMT_RGB48LE || @@ -1192,13 +1197,22 @@ static int decode_frame(AVCodecContext *avctx, } if (s->invert) { - dst = p->data[0]; + dst = p->data[plane]; for (i = 0; i < s->height; i++) { - for (j = 0; j < p->linesize[0]; j++) + for (j = 0; j < p->linesize[plane]; j++) dst[j] = (s->avctx->pix_fmt == AV_PIX_FMT_PAL8 ? (1<bpp) - 1 : 255) - dst[j]; - dst += p->linesize[0]; + dst += p->linesize[plane]; } } + } + + if (s->planar && s->bpp_count > 2) { + FFSWAP(uint8_t*, p->data[0], p->data[2]); + FFSWAP(int, p->linesize[0], p->linesize[2]); + FFSWAP(uint8_t*, p->data[0], p->data[1]); + FFSWAP(int, p->linesize[0], p->linesize[1]); + } + *got_frame = 1; return avpkt->size;