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".