Browse code

tiff: support decoding GBRP and GBRAP formats

Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>

Paul B Mahol authored on 2014/12/17 22:54:44
Showing 1 changed files
... ...
@@ -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;