GetByteContext gb;
int get_subimage;
+ uint16_t get_page;
int width, height;
unsigned int bpp, bppcount;
unsigned white_level;
uint32_t sub_ifd;
+ uint16_t cur_page;
int strips, rps, sstype;
int sot;
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);
uint8_t *dst;
GetByteContext stripsizes;
GetByteContext stripdata;
+ int retry_for_subifd, retry_for_page;
bytestream2_init(&s->gb, avpkt->data, avpkt->size);
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
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;
#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 },
};