Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
Paul B Mahol authored on 2014/12/17 22:54:44... | ... |
@@ -52,6 +52,7 @@ typedef struct TiffContext { |
52 | 52 |
int le; |
53 | 53 |
enum TiffCompr compr; |
54 | 54 |
enum TiffPhotometric photometric; |
55 |
+ int planar; |
|
55 | 56 |
int fax_opts; |
56 | 57 |
int predictor; |
57 | 58 |
int fill_order; |
... | ... |
@@ -172,6 +173,9 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride, |
172 | 172 |
int c, line, pixels, code, ret; |
173 | 173 |
int width = ((s->width * s->bpp) + 7) >> 3; |
174 | 174 |
|
175 |
+ if (s->planar) |
|
176 |
+ width /= s->bppcount; |
|
177 |
+ |
|
175 | 178 |
if (size <= 0) |
176 | 179 |
return AVERROR_INVALIDDATA; |
177 | 180 |
|
... | ... |
@@ -248,7 +252,7 @@ static int init_image(TiffContext *s, AVFrame *frame) |
248 | 248 |
{ |
249 | 249 |
int ret; |
250 | 250 |
|
251 |
- switch (s->bpp * 10 + s->bppcount) { |
|
251 |
+ switch (s->planar * 1000 + s->bpp * 10 + s->bppcount) { |
|
252 | 252 |
case 11: |
253 | 253 |
s->avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; |
254 | 254 |
break; |
... | ... |
@@ -276,6 +280,18 @@ static int init_image(TiffContext *s, AVFrame *frame) |
276 | 276 |
case 644: |
277 | 277 |
s->avctx->pix_fmt = s->le ? AV_PIX_FMT_RGBA64LE : AV_PIX_FMT_RGBA64BE; |
278 | 278 |
break; |
279 |
+ case 1243: |
|
280 |
+ s->avctx->pix_fmt = AV_PIX_FMT_GBRP; |
|
281 |
+ break; |
|
282 |
+ case 1324: |
|
283 |
+ s->avctx->pix_fmt = AV_PIX_FMT_GBRAP; |
|
284 |
+ break; |
|
285 |
+ case 1483: |
|
286 |
+ s->avctx->pix_fmt = s->le ? AV_PIX_FMT_GBRP16LE : AV_PIX_FMT_GBRP16BE; |
|
287 |
+ break; |
|
288 |
+ case 1644: |
|
289 |
+ s->avctx->pix_fmt = s->le ? AV_PIX_FMT_GBRAP16LE : AV_PIX_FMT_GBRAP16BE; |
|
290 |
+ break; |
|
279 | 291 |
default: |
280 | 292 |
av_log(s->avctx, AV_LOG_ERROR, |
281 | 293 |
"This format is not supported (bpp=%d, bppcount=%d)\n", |
... | ... |
@@ -507,10 +523,7 @@ static int tiff_decode_tag(TiffContext *s) |
507 | 507 |
break; |
508 | 508 |
} |
509 | 509 |
case TIFF_PLANAR: |
510 |
- if (value == 2) { |
|
511 |
- avpriv_report_missing_feature(s->avctx, "Planar format"); |
|
512 |
- return AVERROR_PATCHWELCOME; |
|
513 |
- } |
|
510 |
+ s->planar = value == 2; |
|
514 | 511 |
break; |
515 | 512 |
case TIFF_T4OPTIONS: |
516 | 513 |
if (s->compr == TIFF_G3) |
... | ... |
@@ -538,7 +551,7 @@ static int decode_frame(AVCodecContext *avctx, |
538 | 538 |
TiffContext *const s = avctx->priv_data; |
539 | 539 |
AVFrame *const p = data; |
540 | 540 |
unsigned off; |
541 |
- int id, le, ret; |
|
541 |
+ int id, le, ret, plane, planes; |
|
542 | 542 |
int i, j, entries, stride; |
543 | 543 |
unsigned soff, ssize; |
544 | 544 |
uint8_t *dst; |
... | ... |
@@ -596,8 +609,6 @@ static int decode_frame(AVCodecContext *avctx, |
596 | 596 |
av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); |
597 | 597 |
s->stripsize = avpkt->size - s->stripoff; |
598 | 598 |
} |
599 |
- stride = p->linesize[0]; |
|
600 |
- dst = p->data[0]; |
|
601 | 599 |
|
602 | 600 |
if (s->stripsizesoff) { |
603 | 601 |
if (s->stripsizesoff >= avpkt->size) |
... | ... |
@@ -612,64 +623,77 @@ static int decode_frame(AVCodecContext *avctx, |
612 | 612 |
avpkt->size - s->strippos); |
613 | 613 |
} |
614 | 614 |
|
615 |
- for (i = 0; i < s->height; i += s->rps) { |
|
616 |
- if (s->stripsizesoff) |
|
617 |
- ssize = tget(&stripsizes, s->sstype, le); |
|
618 |
- else |
|
619 |
- ssize = s->stripsize; |
|
620 |
- |
|
621 |
- if (s->strippos) |
|
622 |
- soff = tget(&stripdata, s->sot, le); |
|
623 |
- else |
|
624 |
- soff = s->stripoff; |
|
625 |
- |
|
626 |
- if (soff > avpkt->size || ssize > avpkt->size - soff) { |
|
627 |
- av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n"); |
|
628 |
- return AVERROR_INVALIDDATA; |
|
629 |
- } |
|
630 |
- if ((ret = tiff_unpack_strip(s, dst, stride, avpkt->data + soff, ssize, |
|
631 |
- FFMIN(s->rps, s->height - i))) < 0) { |
|
632 |
- if (avctx->err_recognition & AV_EF_EXPLODE) |
|
633 |
- return ret; |
|
634 |
- break; |
|
635 |
- } |
|
636 |
- dst += s->rps * stride; |
|
637 |
- } |
|
638 |
- if (s->predictor == 2) { |
|
639 |
- dst = p->data[0]; |
|
640 |
- soff = s->bpp >> 3; |
|
641 |
- ssize = s->width * soff; |
|
642 |
- if (s->avctx->pix_fmt == AV_PIX_FMT_RGB48LE || |
|
643 |
- s->avctx->pix_fmt == AV_PIX_FMT_RGBA64LE) { |
|
644 |
- for (i = 0; i < s->height; i++) { |
|
645 |
- for (j = soff; j < ssize; j += 2) |
|
646 |
- AV_WL16(dst + j, AV_RL16(dst + j) + AV_RL16(dst + j - soff)); |
|
647 |
- dst += stride; |
|
615 |
+ planes = s->planar ? s->bppcount : 1; |
|
616 |
+ for (plane = 0; plane < planes; plane++) { |
|
617 |
+ stride = p->linesize[plane]; |
|
618 |
+ dst = p->data[plane]; |
|
619 |
+ for (i = 0; i < s->height; i += s->rps) { |
|
620 |
+ if (s->stripsizesoff) |
|
621 |
+ ssize = tget(&stripsizes, s->sstype, le); |
|
622 |
+ else |
|
623 |
+ ssize = s->stripsize; |
|
624 |
+ |
|
625 |
+ if (s->strippos) |
|
626 |
+ soff = tget(&stripdata, s->sot, le); |
|
627 |
+ else |
|
628 |
+ soff = s->stripoff; |
|
629 |
+ |
|
630 |
+ if (soff > avpkt->size || ssize > avpkt->size - soff) { |
|
631 |
+ av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n"); |
|
632 |
+ return AVERROR_INVALIDDATA; |
|
648 | 633 |
} |
649 |
- } else if (s->avctx->pix_fmt == AV_PIX_FMT_RGB48BE || |
|
650 |
- s->avctx->pix_fmt == AV_PIX_FMT_RGBA64BE) { |
|
651 |
- for (i = 0; i < s->height; i++) { |
|
652 |
- for (j = soff; j < ssize; j += 2) |
|
653 |
- AV_WB16(dst + j, AV_RB16(dst + j) + AV_RB16(dst + j - soff)); |
|
654 |
- dst += stride; |
|
634 |
+ if ((ret = tiff_unpack_strip(s, dst, stride, avpkt->data + soff, ssize, |
|
635 |
+ FFMIN(s->rps, s->height - i))) < 0) { |
|
636 |
+ if (avctx->err_recognition & AV_EF_EXPLODE) |
|
637 |
+ return ret; |
|
638 |
+ break; |
|
655 | 639 |
} |
656 |
- } else { |
|
640 |
+ dst += s->rps * stride; |
|
641 |
+ } |
|
642 |
+ if (s->predictor == 2) { |
|
643 |
+ dst = p->data[plane]; |
|
644 |
+ soff = s->bpp >> 3; |
|
645 |
+ ssize = s->width * soff; |
|
646 |
+ if (s->avctx->pix_fmt == AV_PIX_FMT_RGB48LE || |
|
647 |
+ s->avctx->pix_fmt == AV_PIX_FMT_RGBA64LE) { |
|
648 |
+ for (i = 0; i < s->height; i++) { |
|
649 |
+ for (j = soff; j < ssize; j += 2) |
|
650 |
+ AV_WL16(dst + j, AV_RL16(dst + j) + AV_RL16(dst + j - soff)); |
|
651 |
+ dst += stride; |
|
652 |
+ } |
|
653 |
+ } else if (s->avctx->pix_fmt == AV_PIX_FMT_RGB48BE || |
|
654 |
+ s->avctx->pix_fmt == AV_PIX_FMT_RGBA64BE) { |
|
655 |
+ for (i = 0; i < s->height; i++) { |
|
656 |
+ for (j = soff; j < ssize; j += 2) |
|
657 |
+ AV_WB16(dst + j, AV_RB16(dst + j) + AV_RB16(dst + j - soff)); |
|
658 |
+ dst += stride; |
|
659 |
+ } |
|
660 |
+ } else { |
|
661 |
+ for (i = 0; i < s->height; i++) { |
|
662 |
+ for (j = soff; j < ssize; j++) |
|
663 |
+ dst[j] += dst[j - soff]; |
|
664 |
+ dst += stride; |
|
665 |
+ } |
|
666 |
+ } |
|
667 |
+ } |
|
668 |
+ |
|
669 |
+ if (s->photometric == TIFF_PHOTOMETRIC_WHITE_IS_ZERO) { |
|
670 |
+ dst = p->data[plane]; |
|
657 | 671 |
for (i = 0; i < s->height; i++) { |
658 |
- for (j = soff; j < ssize; j++) |
|
659 |
- dst[j] += dst[j - soff]; |
|
672 |
+ for (j = 0; j < stride; j++) |
|
673 |
+ dst[j] = 255 - dst[j]; |
|
660 | 674 |
dst += stride; |
661 | 675 |
} |
662 | 676 |
} |
663 | 677 |
} |
664 | 678 |
|
665 |
- if (s->photometric == TIFF_PHOTOMETRIC_WHITE_IS_ZERO) { |
|
666 |
- dst = p->data[0]; |
|
667 |
- for (i = 0; i < s->height; i++) { |
|
668 |
- for (j = 0; j < p->linesize[0]; j++) |
|
669 |
- dst[j] = 255 - dst[j]; |
|
670 |
- dst += stride; |
|
671 |
- } |
|
679 |
+ if (s->planar && s->bppcount > 2) { |
|
680 |
+ FFSWAP(uint8_t*, p->data[0], p->data[2]); |
|
681 |
+ FFSWAP(int, p->linesize[0], p->linesize[2]); |
|
682 |
+ FFSWAP(uint8_t*, p->data[0], p->data[1]); |
|
683 |
+ FFSWAP(int, p->linesize[0], p->linesize[1]); |
|
672 | 684 |
} |
685 |
+ |
|
673 | 686 |
*got_frame = 1; |
674 | 687 |
|
675 | 688 |
return avpkt->size; |