X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Ftiff.c;h=819672eea0c454e987912a02c29da795271f583b;hb=e83717e63eab1f1b78dc0990e5b8e927097fca29;hp=112f5b52f472b236f41f2dd03b13de4ed6a7a9c9;hpb=c2631dfd0a0a12050cc1765fd41702c5e93abee5;p=ffmpeg diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 112f5b52f47..819672eea0c 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -35,6 +35,7 @@ #include "libavutil/attributes.h" #include "libavutil/avstring.h" +#include "libavutil/error.h" #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" @@ -46,6 +47,7 @@ #include "mathops.h" #include "tiff.h" #include "tiff_data.h" +#include "mjpegdec.h" #include "thread.h" #include "get_bits.h" @@ -54,8 +56,16 @@ typedef struct TiffContext { AVCodecContext *avctx; GetByteContext gb; + /* JPEG decoding for DNG */ + AVCodecContext *avctx_mjpeg; // wrapper context for MJPEG + AVPacket *jpkt; // encoded JPEG tile + AVFrame *jpgframe; // decoded JPEG tile + int get_subimage; + uint16_t get_page; + int get_thumbnail; + enum TiffType tiff_type; int width, height; unsigned int bpp, bppcount; uint32_t palette[256]; @@ -69,29 +79,45 @@ typedef struct TiffContext { int predictor; int fill_order; uint32_t res[4]; + int is_thumbnail; + unsigned last_tag; int is_bayer; uint8_t pattern[4]; + unsigned black_level; unsigned white_level; + uint16_t dng_lut[65536]; uint32_t sub_ifd; + uint16_t cur_page; int strips, rps, sstype; int sot; int stripsizesoff, stripsize, stripoff, strippos; LZWState *lzw; + /* Tile support */ + int is_tiled; + int tile_byte_counts_offset, tile_offsets_offset; + int tile_width, tile_length; + int tile_count; + + int is_jpeg; + uint8_t *deinvert_buf; int deinvert_buf_size; uint8_t *yuv_line; unsigned int yuv_line_size; - uint8_t *fax_buffer; - unsigned int fax_buffer_size; int geotag_count; TiffGeoTag *geotags; } TiffContext; +static void tiff_set_type(TiffContext *s, enum TiffType tiff_type) { + if (s->tiff_type < tiff_type) // Prioritize higher-valued entries + s->tiff_type = tiff_type; +} + static void free_geotags(TiffContext *const s) { int i; @@ -105,8 +131,8 @@ static void free_geotags(TiffContext *const s) #define RET_GEOKEY(TYPE, array, element)\ if (key >= TIFF_##TYPE##_KEY_ID_OFFSET &&\ - key - TIFF_##TYPE##_KEY_ID_OFFSET < FF_ARRAY_ELEMS(ff_tiff_##array##_name_type_map))\ - return ff_tiff_##array##_name_type_map[key - TIFF_##TYPE##_KEY_ID_OFFSET].element; + key - TIFF_##TYPE##_KEY_ID_OFFSET < FF_ARRAY_ELEMS(tiff_##array##_name_type_map))\ + return tiff_##array##_name_type_map[key - TIFF_##TYPE##_KEY_ID_OFFSET].element; static const char *get_geokey_name(int key) { @@ -153,8 +179,8 @@ static char *get_geokey_val(int key, int val) #define RET_GEOKEY_VAL(TYPE, array)\ if (val >= TIFF_##TYPE##_OFFSET &&\ - val - TIFF_##TYPE##_OFFSET < FF_ARRAY_ELEMS(ff_tiff_##array##_codes))\ - return av_strdup(ff_tiff_##array##_codes[val - TIFF_##TYPE##_OFFSET]); + val - TIFF_##TYPE##_OFFSET < FF_ARRAY_ELEMS(tiff_##array##_codes))\ + return av_strdup(tiff_##array##_codes[val - TIFF_##TYPE##_OFFSET]); switch (key) { case TIFF_GT_MODEL_TYPE_GEOKEY: @@ -187,11 +213,11 @@ static char *get_geokey_val(int key, int val) RET_GEOKEY_VAL(PRIME_MERIDIAN, prime_meridian); break; case TIFF_PROJECTED_CS_TYPE_GEOKEY: - ap = av_strdup(search_keyval(ff_tiff_proj_cs_type_codes, FF_ARRAY_ELEMS(ff_tiff_proj_cs_type_codes), val)); + ap = av_strdup(search_keyval(tiff_proj_cs_type_codes, FF_ARRAY_ELEMS(tiff_proj_cs_type_codes), val)); if(ap) return ap; break; case TIFF_PROJECTION_GEOKEY: - ap = av_strdup(search_keyval(ff_tiff_projection_codes, FF_ARRAY_ELEMS(ff_tiff_projection_codes), val)); + ap = av_strdup(search_keyval(tiff_projection_codes, FF_ARRAY_ELEMS(tiff_projection_codes), val)); if(ap) return ap; break; case TIFF_PROJ_COORD_TRANS_GEOKEY: @@ -247,6 +273,102 @@ static int add_metadata(int count, int type, }; } +/** + * Map stored raw sensor values into linear reference values (see: DNG Specification - Chapter 5) + */ +static uint16_t av_always_inline dng_process_color16(uint16_t value, + const uint16_t *lut, + uint16_t black_level, + float scale_factor) +{ + float value_norm; + + // Lookup table lookup + if (lut) + value = lut[value]; + + // Black level subtraction + value = av_clip_uint16_c((unsigned)value - black_level); + + // Color scaling + value_norm = (float)value * scale_factor; + + value = av_clip_uint16_c(value_norm * 65535); + + return value; +} + +static uint16_t av_always_inline dng_process_color8(uint16_t value, + const uint16_t *lut, + uint16_t black_level, + float scale_factor) +{ + return dng_process_color16(value, lut, black_level, scale_factor) >> 8; +} + +static void av_always_inline dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, + const uint8_t *src, int src_stride, int width, int height, + int is_single_comp, int is_u16) +{ + int line, col; + float scale_factor; + + scale_factor = 1.0f / (s->white_level - s->black_level); + + if (is_single_comp) { + if (!is_u16) + return; /* <= 8bpp unsupported */ + + /* Image is double the width and half the height we need, each row comprises 2 rows of the output + (split vertically in the middle). */ + for (line = 0; line < height / 2; line++) { + uint16_t *dst_u16 = (uint16_t *)dst; + uint16_t *src_u16 = (uint16_t *)src; + + /* Blit first half of input row row to initial row of output */ + for (col = 0; col < width; col++) + *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor); + + /* Advance the destination pointer by a row (source pointer remains in the same place) */ + dst += dst_stride * sizeof(uint16_t); + dst_u16 = (uint16_t *)dst; + + /* Blit second half of input row row to next row of output */ + for (col = 0; col < width; col++) + *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor); + + dst += dst_stride * sizeof(uint16_t); + src += src_stride * sizeof(uint16_t); + } + } else { + /* Input and output image are the same size and the MJpeg decoder has done per-component + deinterleaving, so blitting here is straightforward. */ + if (is_u16) { + for (line = 0; line < height; line++) { + uint16_t *dst_u16 = (uint16_t *)dst; + uint16_t *src_u16 = (uint16_t *)src; + + for (col = 0; col < width; col++) + *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor); + + dst += dst_stride * sizeof(uint16_t); + src += src_stride * sizeof(uint16_t); + } + } else { + for (line = 0; line < height; line++) { + uint8_t *dst_u8 = dst; + const uint8_t *src_u8 = src; + + for (col = 0; col < width; col++) + *dst_u8++ = dng_process_color8(*src_u8++, s->dng_lut, s->black_level, scale_factor); + + dst += dst_stride; + src += src_stride; + } + } + } +} + static void av_always_inline horizontal_fill(TiffContext *s, unsigned int bpp, uint8_t* dst, int usePtr, const uint8_t *src, @@ -279,14 +401,19 @@ static void av_always_inline horizontal_fill(TiffContext *s, dst[(width+offset)*2+0] = (usePtr ? src[width] : c) >> 4; } break; - case 12: { - uint16_t *dst16 = (uint16_t *)dst; - GetBitContext gb; - init_get_bits8(&gb, src, width); - for (int i = 0; i < s->width; i++) { - dst16[i] = get_bits(&gb, 12) << 4; - } - } + case 10: + case 12: + case 14: { + uint16_t *dst16 = (uint16_t *)dst; + int is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + uint8_t shift = is_dng ? 0 : 16 - bpp; + GetBitContext gb; + + init_get_bits8(&gb, src, width); + for (int i = 0; i < s->width; i++) { + dst16[i] = get_bits(&gb, bpp) << shift; + } + } break; default: if (usePtr) { @@ -358,7 +485,7 @@ static int tiff_uncompress(uint8_t *dst, unsigned long *len, const uint8_t *src, z_stream zstream = { 0 }; int zret; - zstream.next_in = (uint8_t *)src; + zstream.next_in = src; zstream.avail_in = size; zstream.next_out = dst; zstream.avail_out = *len; @@ -486,27 +613,15 @@ static int tiff_unpack_lzma(TiffContext *s, AVFrame *p, uint8_t *dst, int stride static int tiff_unpack_fax(TiffContext *s, uint8_t *dst, int stride, const uint8_t *src, int size, int width, int lines) { - int i, ret = 0; int line; - uint8_t *src2; - - av_fast_padded_malloc(&s->fax_buffer, &s->fax_buffer_size, size); - src2 = s->fax_buffer; - - if (!src2) { - av_log(s->avctx, AV_LOG_ERROR, - "Error allocating temporary buffer\n"); - return AVERROR(ENOMEM); - } + int ret; - if (!s->fill_order) { - memcpy(src2, src, size); - } else { - for (i = 0; i < size; i++) - src2[i] = ff_reverse[src[i]]; + if (s->fill_order) { + if ((ret = deinvert_buffer(s, src, size)) < 0) + return ret; + src = s->deinvert_buf; } - memset(src2 + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); - ret = ff_ccitt_unpack(s->avctx, src2, size, dst, lines, stride, + ret = ff_ccitt_unpack(s->avctx, src, size, dst, lines, stride, s->compr, s->fax_opts); if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8) for (line = 0; line < lines; line++) { @@ -516,6 +631,109 @@ static int tiff_unpack_fax(TiffContext *s, uint8_t *dst, int stride, return ret; } +static int dng_decode_jpeg(AVCodecContext *avctx, AVFrame *frame, + int tile_byte_count, int dst_x, int dst_y, int w, int h) +{ + TiffContext *s = avctx->priv_data; + uint8_t *dst_data, *src_data; + uint32_t dst_offset; /* offset from dst buffer in pixels */ + int is_single_comp, is_u16, pixel_size; + int ret; + + if (tile_byte_count < 0 || tile_byte_count > bytestream2_get_bytes_left(&s->gb)) + return AVERROR_INVALIDDATA; + + /* Prepare a packet and send to the MJPEG decoder */ + av_packet_unref(s->jpkt); + s->jpkt->data = (uint8_t*)s->gb.buffer; + s->jpkt->size = tile_byte_count; + + if (s->is_bayer) { + MJpegDecodeContext *mjpegdecctx = s->avctx_mjpeg->priv_data; + /* We have to set this information here, there is no way to know if a given JPEG is a DNG-embedded + image or not from its own data (and we need that information when decoding it). */ + mjpegdecctx->bayer = 1; + } + + ret = avcodec_send_packet(s->avctx_mjpeg, s->jpkt); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); + return ret; + } + + ret = avcodec_receive_frame(s->avctx_mjpeg, s->jpgframe); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "JPEG decoding error: %s.\n", av_err2str(ret)); + + /* Normally skip, error if explode */ + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + else + return 0; + } + + is_u16 = (s->bpp > 8); + + /* Copy the outputted tile's pixels from 'jpgframe' to 'frame' (final buffer) */ + + if (s->jpgframe->width != s->avctx_mjpeg->width || + s->jpgframe->height != s->avctx_mjpeg->height || + s->jpgframe->format != s->avctx_mjpeg->pix_fmt) + return AVERROR_INVALIDDATA; + + /* See dng_blit for explanation */ + if (s->avctx_mjpeg->width == w * 2 && + s->avctx_mjpeg->height == h / 2 && + s->avctx_mjpeg->pix_fmt == AV_PIX_FMT_GRAY16LE) { + is_single_comp = 1; + } else if (s->avctx_mjpeg->width >= w && + s->avctx_mjpeg->height >= h && + s->avctx_mjpeg->pix_fmt == (is_u16 ? AV_PIX_FMT_GRAY16 : AV_PIX_FMT_GRAY8) + ) { + is_single_comp = 0; + } else + return AVERROR_INVALIDDATA; + + pixel_size = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t)); + + if (is_single_comp && !is_u16) { + av_log(s->avctx, AV_LOG_ERROR, "DNGs with bpp <= 8 and 1 component are unsupported\n"); + av_frame_unref(s->jpgframe); + return AVERROR_PATCHWELCOME; + } + + dst_offset = dst_x + frame->linesize[0] * dst_y / pixel_size; + dst_data = frame->data[0] + dst_offset * pixel_size; + src_data = s->jpgframe->data[0]; + + dng_blit(s, + dst_data, + frame->linesize[0] / pixel_size, + src_data, + s->jpgframe->linesize[0] / pixel_size, + w, + h, + is_single_comp, + is_u16); + + av_frame_unref(s->jpgframe); + + return 0; +} + +static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame) +{ + TiffContext *s = avctx->priv_data; + + s->jpgframe->width = s->width; + s->jpgframe->height = s->height; + + s->avctx_mjpeg->width = s->width; + s->avctx_mjpeg->height = s->height; + + return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height); +} + static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int stride, const uint8_t *src, int size, int strip_start, int lines) { @@ -527,6 +745,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid int is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB) && (desc->flags & AV_PIX_FMT_FLAG_PLANAR) && desc->nb_components >= 3; + int is_dng; if (s->planar) width /= s->bppcount; @@ -551,7 +770,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid av_assert0(s->bpp == 24); } if (s->is_bayer) { - width = (s->bpp * s->width + 7) >> 3; + av_assert0(width == (s->bpp * s->width + 7) >> 3); } if (p->format == AV_PIX_FMT_GRAY12) { av_fast_padded_malloc(&s->yuv_line, &s->yuv_line_size, width); @@ -628,6 +847,22 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid bytestream2_init(&s->gb, src, size); bytestream2_init_writer(&pb, dst, is_yuv ? s->yuv_line_size : (stride * lines)); + is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + + /* Decode JPEG-encoded DNGs with strips */ + if (s->compr == TIFF_NEWJPEG && is_dng) { + if (s->strips > 1) { + av_log(s->avctx, AV_LOG_ERROR, "More than one DNG JPEG strips unsupported\n"); + return AVERROR_PATCHWELCOME; + } + if ((ret = dng_decode_strip(s->avctx, p)) < 0) + return ret; + return 0; + } + + if (is_dng && stride == 0) + return AVERROR_INVALIDDATA; + for (line = 0; line < lines; line++) { if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); @@ -650,6 +885,28 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid for (i = 0; i < width; i++) dst[i] = ff_reverse[src[i]]; } + + /* Color processing for DNG images with uncompressed strips (non-tiled) */ + if (is_dng) { + int is_u16, pixel_size_bytes, pixel_size_bits, elements; + + is_u16 = (s->bpp / s->bppcount > 8); + pixel_size_bits = (is_u16 ? 16 : 8); + pixel_size_bytes = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t)); + + elements = width / pixel_size_bytes * pixel_size_bits / s->bpp * s->bppcount; // need to account for [1, 16] bpp + av_assert0 (elements * pixel_size_bytes <= FFABS(stride)); + dng_blit(s, + dst, + 0, // no stride, only 1 line + dst, + 0, // no stride, only 1 line + elements, + 1, + 0, // single-component variation is only preset in JPEG-encoded DNGs + is_u16); + } + src += width; break; case TIFF_PACKBITS: @@ -702,6 +959,82 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid return 0; } +static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, + const AVPacket *avpkt) +{ + TiffContext *s = avctx->priv_data; + int tile_idx; + int tile_offset_offset, tile_offset; + int tile_byte_count_offset, tile_byte_count; + int tile_count_x, tile_count_y; + int tile_width, tile_length; + int has_width_leftover, has_height_leftover; + int tile_x = 0, tile_y = 0; + int pos_x = 0, pos_y = 0; + int ret; + + s->jpgframe->width = s->tile_width; + s->jpgframe->height = s->tile_length; + + s->avctx_mjpeg->width = s->tile_width; + s->avctx_mjpeg->height = s->tile_length; + + has_width_leftover = (s->width % s->tile_width != 0); + has_height_leftover = (s->height % s->tile_length != 0); + + /* Calculate tile counts (round up) */ + tile_count_x = (s->width + s->tile_width - 1) / s->tile_width; + tile_count_y = (s->height + s->tile_length - 1) / s->tile_length; + + /* Iterate over the number of tiles */ + for (tile_idx = 0; tile_idx < s->tile_count; tile_idx++) { + tile_x = tile_idx % tile_count_x; + tile_y = tile_idx / tile_count_x; + + if (has_width_leftover && tile_x == tile_count_x - 1) // If on the right-most tile + tile_width = s->width % s->tile_width; + else + tile_width = s->tile_width; + + if (has_height_leftover && tile_y == tile_count_y - 1) // If on the bottom-most tile + tile_length = s->height % s->tile_length; + else + tile_length = s->tile_length; + + /* Read tile offset */ + tile_offset_offset = s->tile_offsets_offset + tile_idx * sizeof(int); + bytestream2_seek(&s->gb, tile_offset_offset, SEEK_SET); + tile_offset = ff_tget_long(&s->gb, s->le); + + /* Read tile byte size */ + tile_byte_count_offset = s->tile_byte_counts_offset + tile_idx * sizeof(int); + bytestream2_seek(&s->gb, tile_byte_count_offset, SEEK_SET); + tile_byte_count = ff_tget_long(&s->gb, s->le); + + /* Seek to tile data */ + bytestream2_seek(&s->gb, tile_offset, SEEK_SET); + + /* Decode JPEG tile and copy it in the reference frame */ + ret = dng_decode_jpeg(avctx, frame, tile_byte_count, pos_x, pos_y, tile_width, tile_length); + + if (ret < 0) + return ret; + + /* Advance current positions */ + pos_x += tile_width; + if (tile_x == tile_count_x - 1) { // If on the right edge + pos_x = 0; + pos_y += tile_length; + } + } + + /* Frame is ready to be output */ + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + + return avpkt->size; +} + static int init_image(TiffContext *s, ThreadFrame *frame) { int ret; @@ -754,39 +1087,22 @@ static int init_image(TiffContext *s, ThreadFrame *frame) return AVERROR_PATCHWELCOME; } break; + case 10101: case 10121: - switch (AV_RL32(s->pattern)) { - case 0x02010100: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_RGGB16LE : AV_PIX_FMT_BAYER_RGGB16BE; - break; - case 0x00010102: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_BGGR16LE : AV_PIX_FMT_BAYER_BGGR16BE; - break; - case 0x01000201: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_GBRG16LE : AV_PIX_FMT_BAYER_GBRG16BE; - break; - case 0x01020001: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_GRBG16LE : AV_PIX_FMT_BAYER_GRBG16BE; - break; - default: - av_log(s->avctx, AV_LOG_ERROR, "Unsupported Bayer pattern: 0x%X\n", - AV_RL32(s->pattern)); - return AVERROR_PATCHWELCOME; - } - break; + case 10141: case 10161: switch (AV_RL32(s->pattern)) { case 0x02010100: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_RGGB16LE : AV_PIX_FMT_BAYER_RGGB16BE; + s->avctx->pix_fmt = AV_PIX_FMT_BAYER_RGGB16; break; case 0x00010102: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_BGGR16LE : AV_PIX_FMT_BAYER_BGGR16BE; + s->avctx->pix_fmt = AV_PIX_FMT_BAYER_BGGR16; break; case 0x01000201: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_GBRG16LE : AV_PIX_FMT_BAYER_GBRG16BE; + s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GBRG16; break; case 0x01020001: - s->avctx->pix_fmt = s->le ? AV_PIX_FMT_BAYER_GRBG16LE : AV_PIX_FMT_BAYER_GRBG16BE; + s->avctx->pix_fmt = AV_PIX_FMT_BAYER_GRBG16; break; default: av_log(s->avctx, AV_LOG_ERROR, "Unsupported Bayer pattern: 0x%X\n", @@ -827,6 +1143,15 @@ static int init_image(TiffContext *s, ThreadFrame *frame) case 324: s->avctx->pix_fmt = s->photometric == TIFF_PHOTOMETRIC_SEPARATED ? AV_PIX_FMT_RGB0 : AV_PIX_FMT_RGBA; break; + case 405: + if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED) + s->avctx->pix_fmt = AV_PIX_FMT_RGBA; + else { + av_log(s->avctx, AV_LOG_ERROR, + "bpp=40 without PHOTOMETRIC_SEPARATED is unsupported\n"); + return AVERROR_PATCHWELCOME; + } + break; case 483: s->avctx->pix_fmt = s->le ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB48BE; break; @@ -904,7 +1229,9 @@ static void set_sar(TiffContext *s, unsigned tag, unsigned num, unsigned den) static int tiff_decode_tag(TiffContext *s, AVFrame *frame) { - unsigned tag, type, count, off, value = 0, value2 = 0; + AVFrameSideData *sd; + GetByteContext gb_temp; + unsigned tag, type, count, off, value = 0, value2 = 1; // value2 is a denominator so init. to 1 int i, start; int pos; int ret; @@ -914,6 +1241,12 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) if (ret < 0) { goto end; } + if (tag <= s->last_tag) + return AVERROR_INVALIDDATA; + + // We ignore TIFF_STRIP_SIZE as it is sometimes in the logic but wrong order around TIFF_STRIP_OFFS + if (tag != TIFF_STRIP_SIZE) + s->last_tag = tag; off = bytestream2_tell(&s->gb); if (count == 1) { @@ -926,6 +1259,11 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) case TIFF_RATIONAL: value = ff_tget(&s->gb, TIFF_LONG, s->le); value2 = ff_tget(&s->gb, TIFF_LONG, s->le); + if (!value2) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid denominator in rational\n"); + return AVERROR_INVALIDDATA; + } + break; case TIFF_STRING: if (count <= 4) { @@ -937,6 +1275,9 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) } switch (tag) { + case TIFF_SUBFILE: + s->is_thumbnail = (value != 0); + break; case TIFF_WIDTH: s->width = value; break; @@ -944,7 +1285,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) s->height = value; break; case TIFF_BPP: - if (count > 4U) { + if (count > 5 || count <= 0) { av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%d, %d components)\n", value, count); @@ -975,9 +1316,9 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) "Samples per pixel requires a single value, many provided\n"); return AVERROR_INVALIDDATA; } - if (value > 4U) { + if (value > 5 || value <= 0) { av_log(s->avctx, AV_LOG_ERROR, - "Samples per pixel %d is too large\n", value); + "Invalid samples per pixel %d\n", value); return AVERROR_INVALIDDATA; } if (s->bppcount == 1) @@ -1008,8 +1349,8 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) #endif case TIFF_JPEG: case TIFF_NEWJPEG: - avpriv_report_missing_feature(s->avctx, "JPEG compression"); - return AVERROR_PATCHWELCOME; + s->is_jpeg = 1; + break; case TIFF_LZMA: #if CONFIG_LZMA break; @@ -1064,20 +1405,54 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) case TIFF_YRES: set_sar(s, tag, value, value2); break; + case TIFF_TILE_OFFSETS: + s->tile_offsets_offset = off; + s->tile_count = count; + s->is_tiled = 1; + break; case TIFF_TILE_BYTE_COUNTS: + s->tile_byte_counts_offset = off; + break; case TIFF_TILE_LENGTH: - case TIFF_TILE_OFFSETS: + s->tile_length = value; + break; case TIFF_TILE_WIDTH: - av_log(s->avctx, AV_LOG_ERROR, "Tiled images are not supported\n"); - return AVERROR_PATCHWELCOME; + s->tile_width = value; break; case TIFF_PREDICTOR: s->predictor = value; break; case TIFF_SUB_IFDS: - s->sub_ifd = value; + if (count == 1) + s->sub_ifd = value; + else if (count > 1) + s->sub_ifd = ff_tget(&s->gb, TIFF_LONG, s->le); /** Only get the first SubIFD */ + break; + case DNG_LINEARIZATION_TABLE: + if (count > FF_ARRAY_ELEMS(s->dng_lut)) + return AVERROR_INVALIDDATA; + for (int i = 0; i < count; i++) + s->dng_lut[i] = ff_tget(&s->gb, type, s->le); + break; + case DNG_BLACK_LEVEL: + if (count > 1) { /* Use the first value in the pattern (assume they're all the same) */ + if (type == TIFF_RATIONAL) { + value = ff_tget(&s->gb, TIFF_LONG, s->le); + value2 = ff_tget(&s->gb, TIFF_LONG, s->le); + if (!value2) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid black level denominator\n"); + return AVERROR_INVALIDDATA; + } + + s->black_level = value / value2; + } else + s->black_level = ff_tget(&s->gb, type, s->le); + av_log(s->avctx, AV_LOG_WARNING, "Assuming black level pattern values are identical\n"); + } else { + s->black_level = value / value2; + } break; - case TIFF_WHITE_LEVEL: + case DNG_WHITE_LEVEL: s->white_level = value; break; case TIFF_CFA_PATTERN_DIM: @@ -1103,6 +1478,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) case TIFF_PHOTOMETRIC_SEPARATED: case TIFF_PHOTOMETRIC_YCBCR: case TIFF_PHOTOMETRIC_CFA: + case TIFF_PHOTOMETRIC_LINEAR_RAW: // Used by DNG images s->photometric = value; break; case TIFF_PHOTOMETRIC_ALPHA_MASK: @@ -1111,7 +1487,6 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) case TIFF_PHOTOMETRIC_ITU_LAB: case TIFF_PHOTOMETRIC_LOG_L: case TIFF_PHOTOMETRIC_LOG_LUV: - case TIFF_PHOTOMETRIC_LINEAR_RAW: avpriv_report_missing_feature(s->avctx, "PhotometricInterpretation 0x%04X", value); @@ -1198,7 +1573,7 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) break; case TIFF_GEO_KEY_DIRECTORY: if (s->geotag_count) { - avpriv_request_sample(s->avctx, "Multiple geo key directories\n"); + avpriv_request_sample(s->avctx, "Multiple geo key directories"); return AVERROR_INVALIDDATA; } ADD_METADATA(1, "GeoTIFF_Version", NULL); @@ -1289,6 +1664,19 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) } } break; + case TIFF_ICC_PROFILE: + gb_temp = s->gb; + bytestream2_seek(&gb_temp, SEEK_SET, off); + + if (bytestream2_get_bytes_left(&gb_temp) < count) + return AVERROR_INVALIDDATA; + + sd = av_frame_new_side_data(frame, AV_FRAME_DATA_ICC_PROFILE, count); + if (!sd) + return AVERROR(ENOMEM); + + bytestream2_get_bufferu(&gb_temp, sd->data, count); + break; case TIFF_ARTIST: ADD_METADATA(count, "artist", NULL); break; @@ -1318,10 +1706,37 @@ 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); break; + case DNG_VERSION: + if (count == 4) { + unsigned int ver[4]; + ver[0] = ff_tget(&s->gb, type, s->le); + ver[1] = ff_tget(&s->gb, type, s->le); + ver[2] = ff_tget(&s->gb, type, s->le); + ver[3] = ff_tget(&s->gb, type, s->le); + + av_log(s->avctx, AV_LOG_DEBUG, "DNG file, version %u.%u.%u.%u\n", + ver[0], ver[1], ver[2], ver[3]); + + tiff_set_type(s, TIFF_TYPE_DNG); + } + break; + case CINEMADNG_TIME_CODES: + case CINEMADNG_FRAME_RATE: + case CINEMADNG_T_STOP: + case CINEMADNG_REEL_NAME: + case CINEMADNG_CAMERA_LABEL: + tiff_set_type(s, TIFF_TYPE_CINEMADNG); + break; default: if (s->avctx->err_recognition & AV_EF_EXPLODE) { av_log(s->avctx, AV_LOG_ERROR, @@ -1348,13 +1763,16 @@ static int decode_frame(AVCodecContext *avctx, TiffContext *const s = avctx->priv_data; AVFrame *const p = data; ThreadFrame frame = { .f = data }; - unsigned off; + unsigned off, last_off; int le, ret, plane, planes; int i, j, entries, stride; unsigned soff, ssize; uint8_t *dst; GetByteContext stripsizes; GetByteContext stripdata; + int retry_for_subifd, retry_for_page; + int is_dng; + int has_tile_bits, has_strip_bits; bytestream2_init(&s->gb, avpkt->data, avpkt->size); @@ -1368,13 +1786,24 @@ static int decode_frame(AVCodecContext *avctx, } s->le = le; // TIFF_BPP is not a required tag and defaults to 1 + + s->tiff_type = TIFF_TYPE_TIFF; again: + s->is_thumbnail = 0; s->bppcount = s->bpp = 1; s->photometric = TIFF_PHOTOMETRIC_NONE; s->compr = TIFF_RAW; s->fill_order = 0; s->white_level = 0; s->is_bayer = 0; + s->is_tiled = 0; + s->is_jpeg = 0; + s->cur_page = 0; + s->last_tag = 0; + + for (i = 0; i < 65536; i++) + s->dng_lut[i] = i; + free_geotags(s); // Reset these offsets so we can tell if they were set this frame @@ -1389,8 +1818,34 @@ again: return ret; } - if (s->sub_ifd && s->get_subimage) { + if (s->get_thumbnail && !s->is_thumbnail) { + av_log(avctx, AV_LOG_INFO, "No embedded thumbnail present\n"); + return AVERROR_EOF; + } + + /** whether we should process this IFD's SubIFD */ + retry_for_subifd = s->sub_ifd && (s->get_subimage || (!s->get_thumbnail && s->is_thumbnail)); + /** whether we should process 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 + + last_off = off; + 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) { + av_log(avctx, AV_LOG_ERROR, "Requested entry not found\n"); + return AVERROR_INVALIDDATA; + } + if (off <= last_off) { + avpriv_request_sample(s->avctx, "non increasing IFD offset"); + return AVERROR_INVALIDDATA; + } 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; @@ -1399,6 +1854,10 @@ again: goto again; } + /* At this point we've decided on which (Sub)IFD to process */ + + is_dng = (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG); + for (i = 0; igeotag_count; i++) { const char *keyname = get_geokey_name(s->geotags[i].key); if (!keyname) { @@ -1416,43 +1875,112 @@ again: } } - if (!s->strippos && !s->stripoff) { + if (is_dng) { + int bps; + + if (s->bpp % s->bppcount) + return AVERROR_INVALIDDATA; + bps = s->bpp / s->bppcount; + if (bps < 8 || bps > 32) + return AVERROR_INVALIDDATA; + + if (s->white_level == 0) + s->white_level = (1LL << bps) - 1; /* Default value as per the spec */ + + if (s->white_level <= s->black_level) { + av_log(avctx, AV_LOG_ERROR, "BlackLevel (%"PRId32") must be less than WhiteLevel (%"PRId32")\n", + s->black_level, s->white_level); + return AVERROR_INVALIDDATA; + } + + if (s->planar) + return AVERROR_PATCHWELCOME; + } + + if (!s->is_tiled && !s->strippos && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return AVERROR_INVALIDDATA; } + + has_tile_bits = s->is_tiled || s->tile_byte_counts_offset || s->tile_offsets_offset || s->tile_width || s->tile_length || s->tile_count; + has_strip_bits = s->strippos || s->strips || s->stripoff || s->rps || s->sot || s->sstype || s->stripsize || s->stripsizesoff; + + if (has_tile_bits && has_strip_bits) { + int tiled_dng = s->is_tiled && is_dng; + av_log(avctx, tiled_dng ? AV_LOG_WARNING : AV_LOG_ERROR, "Tiled TIFF is not allowed to strip\n"); + if (!tiled_dng) + return AVERROR_INVALIDDATA; + } + /* now we have the data and may start decoding */ if ((ret = init_image(s, &frame)) < 0) return ret; - if (s->strips == 1 && !s->stripsize) { - av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); - s->stripsize = avpkt->size - s->stripoff; - } + if (!s->is_tiled || has_strip_bits) { + if (s->strips == 1 && !s->stripsize) { + av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); + s->stripsize = avpkt->size - s->stripoff; + } - if (s->stripsizesoff) { - if (s->stripsizesoff >= (unsigned)avpkt->size) + if (s->stripsizesoff) { + if (s->stripsizesoff >= (unsigned)avpkt->size) + return AVERROR_INVALIDDATA; + bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, + avpkt->size - s->stripsizesoff); + } + if (s->strippos) { + if (s->strippos >= (unsigned)avpkt->size) + return AVERROR_INVALIDDATA; + bytestream2_init(&stripdata, avpkt->data + s->strippos, + avpkt->size - s->strippos); + } + + if (s->rps <= 0 || s->rps % s->subsampling[1]) { + av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); return AVERROR_INVALIDDATA; - bytestream2_init(&stripsizes, avpkt->data + s->stripsizesoff, - avpkt->size - s->stripsizesoff); + } } - if (s->strippos) { - if (s->strippos >= (unsigned)avpkt->size) - return AVERROR_INVALIDDATA; - bytestream2_init(&stripdata, avpkt->data + s->strippos, - avpkt->size - s->strippos); + + if (s->photometric == TIFF_PHOTOMETRIC_LINEAR_RAW || + s->photometric == TIFF_PHOTOMETRIC_CFA) { + p->color_trc = AVCOL_TRC_LINEAR; + } else if (s->photometric == TIFF_PHOTOMETRIC_BLACK_IS_ZERO) { + p->color_trc = AVCOL_TRC_GAMMA22; } - if (s->rps <= 0 || s->rps % s->subsampling[1]) { - av_log(avctx, AV_LOG_ERROR, "rps %d invalid\n", s->rps); - return AVERROR_INVALIDDATA; + /* Handle DNG images with JPEG-compressed tiles */ + + if (is_dng && s->is_tiled) { + if (!s->is_jpeg) { + avpriv_report_missing_feature(avctx, "DNG uncompressed tiled images"); + return AVERROR_PATCHWELCOME; + } else if (!s->is_bayer) { + avpriv_report_missing_feature(avctx, "DNG JPG-compressed tiled non-bayer-encoded images"); + return AVERROR_PATCHWELCOME; + } else { + if ((ret = dng_decode_tiles(avctx, (AVFrame*)data, avpkt)) > 0) + *got_frame = 1; + return ret; + } } + /* Handle TIFF images and DNG images with uncompressed strips (non-tiled) */ + planes = s->planar ? s->bppcount : 1; for (plane = 0; plane < planes; plane++) { + uint8_t *five_planes = NULL; int remaining = avpkt->size; int decoded_height; stride = p->linesize[plane]; dst = p->data[plane]; + if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED && + s->avctx->pix_fmt == AV_PIX_FMT_RGBA) { + stride = stride * 5 / 4; + five_planes = + dst = av_malloc(stride * s->height); + if (!dst) + return AVERROR(ENOMEM); + } for (i = 0; i < s->height; i += s->rps) { if (i) dst += s->rps * stride; @@ -1468,13 +1996,16 @@ again: if (soff > avpkt->size || ssize > avpkt->size - soff || ssize > remaining) { av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n"); + av_freep(&five_planes); return AVERROR_INVALIDDATA; } remaining -= ssize; if ((ret = tiff_unpack_strip(s, p, dst, stride, avpkt->data + soff, ssize, i, FFMIN(s->rps, s->height - i))) < 0) { - if (avctx->err_recognition & AV_EF_EXPLODE) + if (avctx->err_recognition & AV_EF_EXPLODE) { + av_freep(&five_planes); return ret; + } break; } } @@ -1485,7 +2016,7 @@ again: av_log(s->avctx, AV_LOG_ERROR, "predictor == 2 with YUV is unsupported"); return AVERROR_PATCHWELCOME; } - dst = p->data[plane]; + dst = five_planes ? five_planes : p->data[plane]; soff = s->bpp >> 3; if (s->planar) soff = FFMAX(soff / s->bppcount, 1); @@ -1532,18 +2063,38 @@ again: } if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED && - s->avctx->pix_fmt == AV_PIX_FMT_RGB0) { + (s->avctx->pix_fmt == AV_PIX_FMT_RGB0 || s->avctx->pix_fmt == AV_PIX_FMT_RGBA)) { + int x = s->avctx->pix_fmt == AV_PIX_FMT_RGB0 ? 4 : 5; + uint8_t *src = five_planes ? five_planes : p->data[plane]; dst = p->data[plane]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) { - int k = 255 - dst[4 * j + 3]; - int r = (255 - dst[4 * j ]) * k; - int g = (255 - dst[4 * j + 1]) * k; - int b = (255 - dst[4 * j + 2]) * k; + int k = 255 - src[x * j + 3]; + int r = (255 - src[x * j ]) * k; + int g = (255 - src[x * j + 1]) * k; + int b = (255 - src[x * j + 2]) * k; dst[4 * j ] = r * 257 >> 16; dst[4 * j + 1] = g * 257 >> 16; dst[4 * j + 2] = b * 257 >> 16; - dst[4 * j + 3] = 255; + dst[4 * j + 3] = s->avctx->pix_fmt == AV_PIX_FMT_RGBA ? src[x * j + 4] : 255; + } + src += stride; + dst += p->linesize[plane]; + } + av_freep(&five_planes); + } else if (s->photometric == TIFF_PHOTOMETRIC_SEPARATED && + s->avctx->pix_fmt == AV_PIX_FMT_RGBA64BE) { + dst = p->data[plane]; + for (i = 0; i < s->height; i++) { + for (j = 0; j < s->width; j++) { + uint64_t k = 65535 - AV_RB16(dst + 8 * j + 6); + uint64_t r = (65535 - AV_RB16(dst + 8 * j )) * k; + uint64_t g = (65535 - AV_RB16(dst + 8 * j + 2)) * k; + uint64_t b = (65535 - AV_RB16(dst + 8 * j + 4)) * k; + AV_WB16(dst + 8 * j , r * 65537 >> 32); + AV_WB16(dst + 8 * j + 2, g * 65537 >> 32); + AV_WB16(dst + 8 * j + 4, b * 65537 >> 32); + AV_WB16(dst + 8 * j + 6, 65535); } dst += p->linesize[plane]; } @@ -1557,7 +2108,7 @@ again: FFSWAP(int, p->linesize[0], p->linesize[1]); } - if (s->is_bayer && s->white_level && s->bpp == 16) { + if (s->is_bayer && s->white_level && s->bpp == 16 && !is_dng) { uint16_t *dst = (uint16_t *)p->data[0]; for (i = 0; i < s->height; i++) { for (j = 0; j < s->width; j++) @@ -1574,6 +2125,8 @@ again: static av_cold int tiff_init(AVCodecContext *avctx) { TiffContext *s = avctx->priv_data; + const AVCodec *codec; + int ret; s->width = 0; s->height = 0; @@ -1585,6 +2138,28 @@ static av_cold int tiff_init(AVCodecContext *avctx) return AVERROR(ENOMEM); ff_ccitt_unpack_init(); + /* Allocate JPEG frame */ + s->jpgframe = av_frame_alloc(); + s->jpkt = av_packet_alloc(); + if (!s->jpgframe || !s->jpkt) + return AVERROR(ENOMEM); + + /* Prepare everything needed for JPEG decoding */ + codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG); + if (!codec) + return AVERROR_BUG; + s->avctx_mjpeg = avcodec_alloc_context3(codec); + if (!s->avctx_mjpeg) + return AVERROR(ENOMEM); + s->avctx_mjpeg->flags = avctx->flags; + s->avctx_mjpeg->flags2 = avctx->flags2; + s->avctx_mjpeg->dct_algo = avctx->dct_algo; + s->avctx_mjpeg->idct_algo = avctx->idct_algo; + ret = avcodec_open2(s->avctx_mjpeg, codec, NULL); + if (ret < 0) { + return ret; + } + return 0; } @@ -1599,14 +2174,17 @@ static av_cold int tiff_end(AVCodecContext *avctx) s->deinvert_buf_size = 0; av_freep(&s->yuv_line); s->yuv_line_size = 0; - av_freep(&s->fax_buffer); - s->fax_buffer_size = 0; + av_frame_free(&s->jpgframe); + av_packet_free(&s->jpkt); + avcodec_free_context(&s->avctx_mjpeg); return 0; } #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 }, + { "thumbnail", "decode embedded thumbnail subimage instead if available", OFFSET(get_thumbnail), 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 }, }; @@ -1626,7 +2204,7 @@ AVCodec ff_tiff_decoder = { .init = tiff_init, .close = tiff_end, .decode = decode_frame, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(tiff_init), .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .priv_class = &tiff_decoder_class, };