mirror of https://git.ffmpeg.org/ffmpeg.git
avcodec/tiff: Multi-page support
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 <velocityra@gmail.com>
This commit is contained in:
parent
e995e2395b
commit
93748a2efa
|
@ -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;
|
||||
|
@ -1327,6 +1329,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);
|
||||
|
@ -1364,6 +1372,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);
|
||||
|
||||
|
@ -1384,6 +1393,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
|
||||
|
@ -1398,8 +1408,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;
|
||||
|
@ -1648,6 +1670,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 },
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue