From: Nick Renieris <velocit...@gmail.com>

Option "-page N" (page index N starts from 1) can now be used to specify which 
TIFF page/subfile to decode.

Signed-off-by: Nick Renieris <velocit...@gmail.com>
---
 libavcodec/tiff.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index 29a80a6892..9595681839 100644
--- a/libavcodec/tiff.c
+++ b/libavcodec/tiff.c
@@ -55,6 +55,7 @@ typedef struct TiffContext {
     GetByteContext gb;
 
     int get_subimage;
+    uint16_t get_page;
 
     int width, height;
     unsigned int bpp, bppcount;
@@ -75,6 +76,7 @@ typedef struct TiffContext {
     unsigned white_level;
 
     uint32_t sub_ifd;
+    uint16_t cur_page;
 
     int strips, rps, sstype;
     int sot;
@@ -1322,6 +1324,12 @@ static int tiff_decode_tag(TiffContext *s, AVFrame 
*frame)
         break;
     case TIFF_PAGE_NUMBER:
         ADD_METADATA(count, "page_number", " / ");
+        // need to seek back to re-read the page number
+        bytestream2_seek(&s->gb, -count * sizeof(uint16_t), SEEK_CUR);
+        // read the page number
+        s->cur_page = ff_tget(&s->gb, TIFF_SHORT, s->le);
+        // get back to where we were before the previous seek
+        bytestream2_seek(&s->gb, count * sizeof(uint16_t) - sizeof(uint16_t), 
SEEK_CUR);
         break;
     case TIFF_SOFTWARE_NAME:
         ADD_METADATA(count, "software", NULL);
@@ -1359,6 +1367,7 @@ static int decode_frame(AVCodecContext *avctx,
     uint8_t *dst;
     GetByteContext stripsizes;
     GetByteContext stripdata;
+    int retry_for_subifd, retry_for_page;
 
     bytestream2_init(&s->gb, avpkt->data, avpkt->size);
 
@@ -1379,6 +1388,7 @@ again:
     s->fill_order  = 0;
     s->white_level = 0;
     s->is_bayer    = 0;
+    s->cur_page    = 0;
     free_geotags(s);
 
     // Reset these offsets so we can tell if they were set this frame
@@ -1393,8 +1403,20 @@ again:
             return ret;
     }
 
-    if (s->sub_ifd && s->get_subimage) {
+    /** whether we should look for this IFD's SubIFD */
+    retry_for_subifd = s->sub_ifd && s->get_subimage;
+    /** whether we should look for this multi-page IFD's next page */
+    retry_for_page = s->get_page && s->cur_page + 1 < s->get_page;  // 
get_page is 1-indexed
+
+    if (retry_for_page) {
+        // set offset to the next IFD
+        off = ff_tget_long(&s->gb, le);
+    } else if (retry_for_subifd) {
+        // set offset to the SubIFD
         off = s->sub_ifd;
+    }
+
+    if (retry_for_subifd || retry_for_page) {
         if (off >= UINT_MAX - 14 || avpkt->size < off + 14) {
             av_log(avctx, AV_LOG_ERROR, "IFD offset is greater than image 
size\n");
             return AVERROR_INVALIDDATA;
@@ -1643,6 +1665,7 @@ static av_cold int tiff_end(AVCodecContext *avctx)
 #define OFFSET(x) offsetof(TiffContext, x)
 static const AVOption tiff_options[] = {
     { "subimage", "decode subimage instead if available", 
OFFSET(get_subimage), AV_OPT_TYPE_BOOL, {.i64=0},  0, 1, 
AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM },
+    { "page", "page number of multi-page image to decode (starting from 1)", 
OFFSET(get_page), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT16_MAX, 
AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM },
     { NULL },
 };
 
-- 
2.21.0.windows.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to