]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/tiff.c
Merge commit '4f50646697606df39317b93c2a427603b77636ee'
[ffmpeg] / libavcodec / tiff.c
index 286cbc26a12ea4f35d28499736a2820760adabb1..c16ce137a75c64dc0ebdaba29d320048eea2c9a7 100644 (file)
@@ -62,6 +62,9 @@ typedef struct TiffContext {
     int stripsizesoff, stripsize, stripoff, strippos;
     LZWState *lzw;
 
+    uint8_t *deinvert_buf;
+    int deinvert_buf_size;
+
     int geotag_count;
     TiffGeoTag *geotags;
 } TiffContext;
@@ -396,7 +399,7 @@ static void av_always_inline horizontal_fill(unsigned int bpp, uint8_t* dst,
 static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
                              const uint8_t *src, int size, int lines)
 {
-    int c, line, pixels, code;
+    int c, line, pixels, code, ret;
     const uint8_t *ssrc = src;
     int width = ((s->width * s->bpp) + 7) >> 3;
 
@@ -431,7 +434,7 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
                    (unsigned long)width * lines, ret);
             av_free(src2);
             av_free(zbuf);
-            return -1;
+            return AVERROR_UNKNOWN;
         }
         src = zbuf;
         for (line = 0; line < lines; line++) {
@@ -449,9 +452,22 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
     }
 #endif
     if (s->compr == TIFF_LZW) {
-        if (ff_lzw_decode_init(s->lzw, 8, src, size, FF_LZW_TIFF) < 0) {
+        if (s->fill_order) {
+            int i;
+            av_fast_padded_malloc(&s->deinvert_buf, &s->deinvert_buf_size, size);
+            if (!s->deinvert_buf)
+                return AVERROR(ENOMEM);
+            for (i = 0; i < size; i++)
+                s->deinvert_buf[i] = ff_reverse[src[i]];
+            src = s->deinvert_buf;
+            ssrc = src;
+        }
+        if (size > 1 && !src[0] && (src[1]&1)) {
+            av_log(s->avctx, AV_LOG_ERROR, "Old style LZW is unsupported\n");
+        }
+        if ((ret = ff_lzw_decode_init(s->lzw, 8, src, size, FF_LZW_TIFF)) < 0) {
             av_log(s->avctx, AV_LOG_ERROR, "Error initializing LZW decoder\n");
-            return -1;
+            return ret;
         }
     }
     if (s->compr == TIFF_CCITT_RLE || s->compr == TIFF_G3
@@ -469,7 +485,7 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
             av_log(s->avctx, AV_LOG_ERROR,
                    "Uncompressed fax mode is not supported (yet)\n");
             av_free(src2);
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         if (!s->fill_order) {
             memcpy(src2, src, size);
@@ -497,7 +513,7 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
     for (line = 0; line < lines; line++) {
         if (src - ssrc > size) {
             av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n");
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         switch (s->compr) {
         case TIFF_RAW:
@@ -525,7 +541,7 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
                     if (pixels + code > width) {
                         av_log(s->avctx, AV_LOG_ERROR,
                                "Copy went out of bounds\n");
-                        return -1;
+                        return AVERROR_INVALIDDATA;
                     }
                     if (ssrc + size - src < code) {
                         av_log(s->avctx, AV_LOG_ERROR, "Read went out of bounds\n");
@@ -540,7 +556,7 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
                     if (pixels + code > width) {
                         av_log(s->avctx, AV_LOG_ERROR,
                                "Run went out of bounds\n");
-                        return -1;
+                        return AVERROR_INVALIDDATA;
                     }
                     c = *src++;
                     horizontal_fill(s->bpp * (s->avctx->pix_fmt == AV_PIX_FMT_PAL8),
@@ -554,7 +570,7 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride,
             if (pixels < width) {
                 av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n",
                        pixels, width);
-                return -1;
+                return AVERROR_INVALIDDATA;
             }
             if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8)
                 horizontal_fill(s->bpp, dst, 1, dst, 0, width, 0);
@@ -689,7 +705,7 @@ static int tiff_decode_tag(TiffContext *s)
             av_log(s->avctx, AV_LOG_ERROR,
                    "This format is not supported (bpp=%d, %d components)\n",
                    s->bpp, count);
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         if (count == 1)
             s->bpp = value;
@@ -703,7 +719,7 @@ static int tiff_decode_tag(TiffContext *s)
             case TIFF_LONG:
                 s->bpp = 0;
                 if (bytestream2_get_bytes_left(&s->gb) < type_sizes[type] * count)
-                    return -1;
+                    return AVERROR_INVALIDDATA;
                 for (i = 0; i < count; i++)
                     s->bpp += tget(&s->gb, type, s->le);
                 break;
@@ -741,26 +757,26 @@ static int tiff_decode_tag(TiffContext *s)
             break;
 #else
             av_log(s->avctx, AV_LOG_ERROR, "Deflate: ZLib not compiled in\n");
-            return -1;
+            return AVERROR(ENOSYS);
 #endif
         case TIFF_JPEG:
         case TIFF_NEWJPEG:
             av_log(s->avctx, AV_LOG_ERROR,
                    "JPEG compression is not supported\n");
-            return -1;
+            return AVERROR_PATCHWELCOME;
         default:
             av_log(s->avctx, AV_LOG_ERROR, "Unknown compression method %i\n",
                    s->compr);
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         break;
     case TIFF_ROWSPERSTRIP:
         if (type == TIFF_LONG && value == UINT_MAX)
-            value = s->avctx->height;
+            value = s->height;
         if (value < 1) {
             av_log(s->avctx, AV_LOG_ERROR,
                    "Incorrect value of rows per strip\n");
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         s->rps = value;
         break;
@@ -777,7 +793,7 @@ static int tiff_decode_tag(TiffContext *s)
         if (s->strippos > bytestream2_size(&s->gb)) {
             av_log(s->avctx, AV_LOG_ERROR,
                    "Tag referencing position outside the image\n");
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         break;
     case TIFF_STRIP_SIZE:
@@ -793,7 +809,7 @@ static int tiff_decode_tag(TiffContext *s)
         if (s->stripsizesoff > bytestream2_size(&s->gb)) {
             av_log(s->avctx, AV_LOG_ERROR,
                    "Tag referencing position outside the image\n");
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         break;
     case TIFF_TILE_BYTE_COUNTS:
@@ -820,7 +836,7 @@ static int tiff_decode_tag(TiffContext *s)
         default:
             av_log(s->avctx, AV_LOG_ERROR, "Color mode %d is not supported\n",
                    value);
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         break;
     case TIFF_FILL_ORDER:
@@ -835,7 +851,7 @@ static int tiff_decode_tag(TiffContext *s)
         pal = (uint32_t *) s->palette;
         off = type_sizes[type];
         if (count / 3 > 256 || bytestream2_get_bytes_left(&s->gb) < count / 3 * off * 3)
-            return -1;
+            return AVERROR_INVALIDDATA;
         off = (type_sizes[type] - 1) << 3;
         for (k = 2; k >= 0; k--) {
             for (i = 0; i < count / 3; i++) {
@@ -850,7 +866,7 @@ static int tiff_decode_tag(TiffContext *s)
     case TIFF_PLANAR:
         if (value == 2) {
             av_log(s->avctx, AV_LOG_ERROR, "Planar format is not supported\n");
-            return -1;
+            return AVERROR_PATCHWELCOME;
         }
         break;
     case TIFF_T4OPTIONS:
@@ -943,7 +959,7 @@ static int tiff_decode_tag(TiffContext *s)
 
                     bytestream2_seek(&s->gb, pos + s->geotags[i].offset, SEEK_SET);
                     if (bytestream2_get_bytes_left(&s->gb) < s->geotags[i].count)
-                        return -1;
+                        return AVERROR_INVALIDDATA;
                     ap = av_malloc(s->geotags[i].count);
                     if (!ap) {
                         av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n");
@@ -1024,7 +1040,7 @@ static int decode_frame(AVCodecContext *avctx,
         le = 0;
     else {
         av_log(avctx, AV_LOG_ERROR, "TIFF header not found\n");
-        return -1;
+        return AVERROR_INVALIDDATA;
     }
     s->le = le;
     // TIFF_BPP is not a required tag and defaults to 1
@@ -1042,7 +1058,7 @@ static int decode_frame(AVCodecContext *avctx,
     if (tget_short(&s->gb, le) != 42) {
         av_log(avctx, AV_LOG_ERROR,
                "The answer to life, universe and everything is not correct!\n");
-        return -1;
+        return AVERROR_INVALIDDATA;
     }
     // Reset these offsets so we can tell if they were set this frame
     s->stripsizesoff = s->strippos = 0;
@@ -1057,8 +1073,8 @@ static int decode_frame(AVCodecContext *avctx,
     if (bytestream2_get_bytes_left(&s->gb) < entries * 12)
         return AVERROR_INVALIDDATA;
     for (i = 0; i < entries; i++) {
-        if (tiff_decode_tag(s) < 0)
-            return -1;
+        if ((ret = tiff_decode_tag(s)) < 0)
+            return ret;
     }
 
     for (i = 0; i<s->geotag_count; i++) {
@@ -1080,7 +1096,7 @@ static int decode_frame(AVCodecContext *avctx,
 
     if (!s->strippos && !s->stripoff) {
         av_log(avctx, AV_LOG_ERROR, "Image data is missing\n");
-        return -1;
+        return AVERROR_INVALIDDATA;
     }
     /* now we have the data and may start decoding */
     if ((ret = init_image(s)) < 0)
@@ -1122,7 +1138,7 @@ static int decode_frame(AVCodecContext *avctx,
 
         if (soff > avpkt->size || ssize > avpkt->size - soff) {
             av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n");
-            return -1;
+            return AVERROR_INVALIDDATA;
         }
         if (tiff_unpack_strip(s, dst, stride, avpkt->data + soff, ssize,
                               FFMIN(s->rps, s->height - i)) < 0)
@@ -1192,6 +1208,7 @@ static av_cold int tiff_end(AVCodecContext *avctx)
     free_geotags(s);
 
     ff_lzw_decode_close(&s->lzw);
+    av_freep(&s->deinvert_buf);
     if (s->picture.data[0])
         avctx->release_buffer(avctx, &s->picture);
     return 0;