2006-10-13 13:48:29 +03:00
/*
* Copyright ( c ) 2006 Konstantin Shishkov
*
* This file is part of FFmpeg .
*
* FFmpeg is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* FFmpeg is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
2007-04-04 14:43:08 +03:00
/**
2010-04-20 17:45:34 +03:00
* @ file
2011-05-09 20:21:26 +03:00
* TIFF image decoder
2007-04-04 14:43:08 +03:00
* @ author Konstantin Shishkov
*/
2011-07-14 04:46:19 +03:00
2012-08-06 16:49:32 +03:00
# include "config.h"
2009-01-14 01:44:16 +02:00
# if CONFIG_ZLIB
2006-10-13 13:48:29 +03:00
# include <zlib.h>
# endif
2014-08-23 05:39:57 +03:00
# if CONFIG_LZMA
2014-11-22 18:43:19 +02:00
# define LZMA_API_STATIC
2014-08-23 05:39:57 +03:00
# include <lzma.h>
# endif
2013-06-01 16:35:11 +03:00
2012-10-11 19:50:30 +03:00
# include "libavutil/attributes.h"
2013-06-03 12:44:11 +03:00
# include "libavutil/avstring.h"
2019-08-29 15:10:41 +02:00
# include "libavutil/error.h"
2009-12-03 21:19:57 +02:00
# include "libavutil/intreadwrite.h"
2011-02-07 15:37:08 +02:00
# include "libavutil/imgutils.h"
2018-10-30 23:05:52 +02:00
# include "libavutil/opt.h"
2013-06-01 16:35:11 +03:00
# include "avcodec.h"
2013-06-03 12:44:11 +03:00
# include "bytestream.h"
2013-06-01 16:35:11 +03:00
# include "faxcompr.h"
# include "internal.h"
# include "lzw.h"
# include "mathops.h"
# include "tiff.h"
2013-06-03 12:44:11 +03:00
# include "tiff_data.h"
2019-08-29 15:10:41 +02:00
# include "mjpegdec.h"
2013-08-09 17:01:46 +03:00
# include "thread.h"
2018-10-30 23:05:52 +02:00
# include "get_bits.h"
2006-11-13 13:34:46 +02:00
2006-10-13 13:48:29 +03:00
typedef struct TiffContext {
2018-10-30 23:05:52 +02:00
AVClass * class ;
2006-10-13 13:48:29 +03:00
AVCodecContext * avctx ;
2012-07-15 23:58:13 +03:00
GetByteContext gb ;
2006-10-13 13:48:29 +03:00
2019-08-29 15:10:41 +02:00
/* JPEG decoding for DNG */
AVCodecContext * avctx_mjpeg ; // wrapper context for MJPEG
AVFrame * jpgframe ; // decoded JPEG tile
2018-10-30 23:05:52 +02:00
int get_subimage ;
2019-03-22 17:55:56 +02:00
uint16_t get_page ;
2019-05-30 12:42:40 +02:00
int get_thumbnail ;
2018-10-30 23:05:52 +02:00
2019-05-30 12:42:42 +02:00
enum TiffType tiff_type ;
2006-10-13 13:48:29 +03:00
int width , height ;
2011-05-09 13:51:24 +03:00
unsigned int bpp , bppcount ;
2011-05-24 02:17:25 +03:00
uint32_t palette [ 256 ] ;
int palette_is_set ;
2006-10-13 13:48:29 +03:00
int le ;
2011-05-09 22:05:42 +03:00
enum TiffCompr compr ;
2013-09-30 07:39:51 +03:00
enum TiffPhotometric photometric ;
2013-05-09 22:39:32 +03:00
int planar ;
2014-04-27 19:44:58 +03:00
int subsampling [ 2 ] ;
2008-12-26 20:42:26 +02:00
int fax_opts ;
2008-12-22 08:50:18 +02:00
int predictor ;
2009-09-24 21:30:28 +03:00
int fill_order ;
2014-04-07 11:39:55 +03:00
uint32_t res [ 4 ] ;
2019-05-30 12:42:40 +02:00
int is_thumbnail ;
2006-10-13 13:48:29 +03:00
2018-10-30 23:05:52 +02:00
int is_bayer ;
uint8_t pattern [ 4 ] ;
2019-08-29 15:10:41 +02:00
unsigned black_level ;
2018-10-30 23:05:52 +02:00
unsigned white_level ;
2019-08-31 21:14:28 +02:00
uint16_t dng_lut [ 65536 ] ;
2018-10-30 23:05:52 +02:00
uint32_t sub_ifd ;
2019-03-22 17:55:56 +02:00
uint16_t cur_page ;
2018-10-30 23:05:52 +02:00
2008-12-22 08:50:18 +02:00
int strips , rps , sstype ;
2006-10-13 13:48:29 +03:00
int sot ;
2012-07-15 23:58:13 +03:00
int stripsizesoff , stripsize , stripoff , strippos ;
2006-10-26 07:15:48 +03:00
LZWState * lzw ;
2011-10-04 01:19:52 +03:00
2019-08-29 15:10:41 +02:00
/* Tile support */
int is_tiled ;
int tile_byte_counts_offset , tile_offsets_offset ;
int tile_width , tile_length ;
int tile_count ;
int is_jpeg ;
2012-12-20 18:36:44 +03:00
uint8_t * deinvert_buf ;
int deinvert_buf_size ;
2014-04-27 20:52:37 +03:00
uint8_t * yuv_line ;
unsigned int yuv_line_size ;
2017-06-03 23:57:58 +02:00
uint8_t * fax_buffer ;
unsigned int fax_buffer_size ;
2012-12-20 18:36:44 +03:00
2011-10-04 01:19:52 +03:00
int geotag_count ;
TiffGeoTag * geotags ;
2006-10-13 13:48:29 +03:00
} TiffContext ;
2019-05-30 12:42:42 +02:00
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 ;
}
2011-10-04 01:19:52 +03:00
static void free_geotags ( TiffContext * const s )
{
int i ;
for ( i = 0 ; i < s - > geotag_count ; i + + ) {
if ( s - > geotags [ i ] . val )
av_freep ( & s - > geotags [ i ] . val ) ;
}
av_freep ( & s - > geotags ) ;
2014-02-02 03:47:36 +03:00
s - > geotag_count = 0 ;
2011-10-04 01:19:52 +03:00
}
# 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 ;
static const char * get_geokey_name ( int key )
{
RET_GEOKEY ( VERT , vert , name ) ;
RET_GEOKEY ( PROJ , proj , name ) ;
RET_GEOKEY ( GEOG , geog , name ) ;
RET_GEOKEY ( CONF , conf , name ) ;
return NULL ;
}
static int get_geokey_type ( int key )
{
RET_GEOKEY ( VERT , vert , type ) ;
RET_GEOKEY ( PROJ , proj , type ) ;
RET_GEOKEY ( GEOG , geog , type ) ;
RET_GEOKEY ( CONF , conf , type ) ;
return AVERROR_INVALIDDATA ;
}
static int cmp_id_key ( const void * id , const void * k )
{
return * ( const int * ) id - ( ( const TiffGeoTagKeyName * ) k ) - > key ;
}
static const char * search_keyval ( const TiffGeoTagKeyName * keys , int n , int id )
{
2013-02-10 22:17:33 +03:00
TiffGeoTagKeyName * r = bsearch ( & id , keys , n , sizeof ( keys [ 0 ] ) , cmp_id_key ) ;
if ( r )
return r - > name ;
return NULL ;
2011-10-04 01:19:52 +03:00
}
static char * get_geokey_val ( int key , int val )
{
char * ap ;
if ( val = = TIFF_GEO_KEY_UNDEFINED )
return av_strdup ( " undefined " ) ;
if ( val = = TIFF_GEO_KEY_USER_DEFINED )
return av_strdup ( " User-Defined " ) ;
# 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 ] ) ;
switch ( key ) {
case TIFF_GT_MODEL_TYPE_GEOKEY :
RET_GEOKEY_VAL ( GT_MODEL_TYPE , gt_model_type ) ;
break ;
case TIFF_GT_RASTER_TYPE_GEOKEY :
RET_GEOKEY_VAL ( GT_RASTER_TYPE , gt_raster_type ) ;
break ;
case TIFF_GEOG_LINEAR_UNITS_GEOKEY :
case TIFF_PROJ_LINEAR_UNITS_GEOKEY :
case TIFF_VERTICAL_UNITS_GEOKEY :
RET_GEOKEY_VAL ( LINEAR_UNIT , linear_unit ) ;
break ;
case TIFF_GEOG_ANGULAR_UNITS_GEOKEY :
case TIFF_GEOG_AZIMUTH_UNITS_GEOKEY :
RET_GEOKEY_VAL ( ANGULAR_UNIT , angular_unit ) ;
break ;
case TIFF_GEOGRAPHIC_TYPE_GEOKEY :
RET_GEOKEY_VAL ( GCS_TYPE , gcs_type ) ;
RET_GEOKEY_VAL ( GCSE_TYPE , gcse_type ) ;
break ;
case TIFF_GEOG_GEODETIC_DATUM_GEOKEY :
RET_GEOKEY_VAL ( GEODETIC_DATUM , geodetic_datum ) ;
RET_GEOKEY_VAL ( GEODETIC_DATUM_E , geodetic_datum_e ) ;
break ;
case TIFF_GEOG_ELLIPSOID_GEOKEY :
RET_GEOKEY_VAL ( ELLIPSOID , ellipsoid ) ;
break ;
case TIFF_GEOG_PRIME_MERIDIAN_GEOKEY :
RET_GEOKEY_VAL ( PRIME_MERIDIAN , prime_meridian ) ;
break ;
case TIFF_PROJECTED_CS_TYPE_GEOKEY :
2013-02-10 22:17:33 +03:00
ap = av_strdup ( search_keyval ( ff_tiff_proj_cs_type_codes , FF_ARRAY_ELEMS ( ff_tiff_proj_cs_type_codes ) , val ) ) ;
if ( ap ) return ap ;
2011-10-04 01:19:52 +03:00
break ;
case TIFF_PROJECTION_GEOKEY :
2013-02-10 22:17:33 +03:00
ap = av_strdup ( search_keyval ( ff_tiff_projection_codes , FF_ARRAY_ELEMS ( ff_tiff_projection_codes ) , val ) ) ;
if ( ap ) return ap ;
2011-10-04 01:19:52 +03:00
break ;
case TIFF_PROJ_COORD_TRANS_GEOKEY :
RET_GEOKEY_VAL ( COORD_TRANS , coord_trans ) ;
break ;
case TIFF_VERTICAL_CS_TYPE_GEOKEY :
RET_GEOKEY_VAL ( VERT_CS , vert_cs ) ;
RET_GEOKEY_VAL ( ORTHO_VERT_CS , ortho_vert_cs ) ;
break ;
}
ap = av_malloc ( 14 ) ;
if ( ap )
snprintf ( ap , 14 , " Unknown-%d " , val ) ;
return ap ;
}
static char * doubles2str ( double * dp , int count , const char * sep )
{
int i ;
char * ap , * ap0 ;
2013-02-13 01:40:24 +03:00
uint64_t component_len ;
2011-10-04 01:19:52 +03:00
if ( ! sep ) sep = " , " ;
2014-02-23 12:30:37 +03:00
component_len = 24LL + strlen ( sep ) ;
2013-02-13 01:40:24 +03:00
if ( count > = ( INT_MAX - 1 ) / component_len )
return NULL ;
ap = av_malloc ( component_len * count + 1 ) ;
2011-10-04 01:19:52 +03:00
if ( ! ap )
return NULL ;
ap0 = ap ;
ap [ 0 ] = ' \0 ' ;
for ( i = 0 ; i < count ; i + + ) {
2014-02-23 12:30:37 +03:00
unsigned l = snprintf ( ap , component_len , " %.15g%s " , dp [ i ] , sep ) ;
2012-10-11 17:51:08 +03:00
if ( l > = component_len ) {
av_free ( ap0 ) ;
2012-09-09 15:41:18 +03:00
return NULL ;
2012-10-11 17:51:08 +03:00
}
2011-10-04 01:19:52 +03:00
ap + = l ;
}
ap0 [ strlen ( ap0 ) - strlen ( sep ) ] = ' \0 ' ;
return ap0 ;
}
2012-07-15 23:58:13 +03:00
static int add_metadata ( int count , int type ,
2013-03-13 20:51:17 +03:00
const char * name , const char * sep , TiffContext * s , AVFrame * frame )
2011-10-04 01:19:52 +03:00
{
switch ( type ) {
2017-04-22 10:54:58 +02:00
case TIFF_DOUBLE : return ff_tadd_doubles_metadata ( count , name , sep , & s - > gb , s - > le , & frame - > metadata ) ;
case TIFF_SHORT : return ff_tadd_shorts_metadata ( count , name , sep , & s - > gb , s - > le , 0 , & frame - > metadata ) ;
case TIFF_STRING : return ff_tadd_string_metadata ( count , name , & s - > gb , s - > le , & frame - > metadata ) ;
2011-10-04 01:19:52 +03:00
default : return AVERROR_INVALIDDATA ;
} ;
}
2019-08-29 15:10:41 +02:00
static void av_always_inline dng_blit ( TiffContext * s , uint8_t * dst , int dst_stride ,
2019-08-29 15:10:49 +02:00
const uint8_t * src , int src_stride , int width , int height ,
int is_single_comp , int is_u16 ) ;
2019-08-29 15:10:41 +02:00
2018-10-30 23:05:52 +02:00
static void av_always_inline horizontal_fill ( TiffContext * s ,
unsigned int bpp , uint8_t * dst ,
2011-08-23 21:38:43 +03:00
int usePtr , const uint8_t * src ,
uint8_t c , int width , int offset )
{
2011-12-31 03:53:22 +03:00
switch ( bpp ) {
2011-12-31 04:00:33 +03:00
case 1 :
while ( - - width > = 0 ) {
dst [ ( width + offset ) * 8 + 7 ] = ( usePtr ? src [ width ] : c ) & 0x1 ;
dst [ ( width + offset ) * 8 + 6 ] = ( usePtr ? src [ width ] : c ) > > 1 & 0x1 ;
dst [ ( width + offset ) * 8 + 5 ] = ( usePtr ? src [ width ] : c ) > > 2 & 0x1 ;
dst [ ( width + offset ) * 8 + 4 ] = ( usePtr ? src [ width ] : c ) > > 3 & 0x1 ;
dst [ ( width + offset ) * 8 + 3 ] = ( usePtr ? src [ width ] : c ) > > 4 & 0x1 ;
dst [ ( width + offset ) * 8 + 2 ] = ( usePtr ? src [ width ] : c ) > > 5 & 0x1 ;
dst [ ( width + offset ) * 8 + 1 ] = ( usePtr ? src [ width ] : c ) > > 6 & 0x1 ;
dst [ ( width + offset ) * 8 + 0 ] = ( usePtr ? src [ width ] : c ) > > 7 ;
}
break ;
2011-12-31 03:53:22 +03:00
case 2 :
2011-12-31 03:58:16 +03:00
while ( - - width > = 0 ) {
dst [ ( width + offset ) * 4 + 3 ] = ( usePtr ? src [ width ] : c ) & 0x3 ;
dst [ ( width + offset ) * 4 + 2 ] = ( usePtr ? src [ width ] : c ) > > 2 & 0x3 ;
dst [ ( width + offset ) * 4 + 1 ] = ( usePtr ? src [ width ] : c ) > > 4 & 0x3 ;
dst [ ( width + offset ) * 4 + 0 ] = ( usePtr ? src [ width ] : c ) > > 6 ;
2011-08-23 21:38:43 +03:00
}
2011-12-31 03:53:22 +03:00
break ;
case 4 :
2011-12-31 03:58:16 +03:00
while ( - - width > = 0 ) {
dst [ ( width + offset ) * 2 + 1 ] = ( usePtr ? src [ width ] : c ) & 0xF ;
dst [ ( width + offset ) * 2 + 0 ] = ( usePtr ? src [ width ] : c ) > > 4 ;
2011-08-23 21:38:43 +03:00
}
2011-12-31 03:53:22 +03:00
break ;
2019-08-29 15:10:50 +02:00
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 ;
}
}
2018-10-30 23:05:52 +02:00
break ;
2011-12-31 03:53:22 +03:00
default :
2011-08-23 21:38:43 +03:00
if ( usePtr ) {
memcpy ( dst + offset , src , width ) ;
} else {
memset ( dst + offset , c , width ) ;
}
}
}
2013-05-28 20:13:26 +03:00
static int deinvert_buffer ( TiffContext * s , const uint8_t * src , int size )
{
int i ;
av_fast_padded_malloc ( & s - > deinvert_buf , & s - > deinvert_buf_size , size ) ;
if ( ! s - > deinvert_buf )
return AVERROR ( ENOMEM ) ;
for ( i = 0 ; i < size ; i + + )
s - > deinvert_buf [ i ] = ff_reverse [ src [ i ] ] ;
return 0 ;
}
2018-12-14 18:32:25 +02:00
static void unpack_gray ( TiffContext * s , AVFrame * p ,
const uint8_t * src , int lnum , int width , int bpp )
{
GetBitContext gb ;
uint16_t * dst = ( uint16_t * ) ( p - > data [ 0 ] + lnum * p - > linesize [ 0 ] ) ;
init_get_bits8 ( & gb , src , width ) ;
for ( int i = 0 ; i < s - > width ; i + + ) {
dst [ i ] = get_bits ( & gb , bpp ) ;
}
}
2014-08-19 23:04:01 +03:00
static void unpack_yuv ( TiffContext * s , AVFrame * p ,
const uint8_t * src , int lnum )
{
int i , j , k ;
int w = ( s - > width - 1 ) / s - > subsampling [ 0 ] + 1 ;
uint8_t * pu = & p - > data [ 1 ] [ lnum / s - > subsampling [ 1 ] * p - > linesize [ 1 ] ] ;
uint8_t * pv = & p - > data [ 2 ] [ lnum / s - > subsampling [ 1 ] * p - > linesize [ 2 ] ] ;
if ( s - > width % s - > subsampling [ 0 ] | | s - > height % s - > subsampling [ 1 ] ) {
for ( i = 0 ; i < w ; i + + ) {
for ( j = 0 ; j < s - > subsampling [ 1 ] ; j + + )
for ( k = 0 ; k < s - > subsampling [ 0 ] ; k + + )
p - > data [ 0 ] [ FFMIN ( lnum + j , s - > height - 1 ) * p - > linesize [ 0 ] +
FFMIN ( i * s - > subsampling [ 0 ] + k , s - > width - 1 ) ] = * src + + ;
* pu + + = * src + + ;
* pv + + = * src + + ;
}
} else {
for ( i = 0 ; i < w ; i + + ) {
for ( j = 0 ; j < s - > subsampling [ 1 ] ; j + + )
for ( k = 0 ; k < s - > subsampling [ 0 ] ; k + + )
p - > data [ 0 ] [ ( lnum + j ) * p - > linesize [ 0 ] +
i * s - > subsampling [ 0 ] + k ] = * src + + ;
* pu + + = * src + + ;
* pv + + = * src + + ;
}
}
}
2009-09-27 12:43:11 +03:00
# if CONFIG_ZLIB
2012-04-13 04:28:37 +03:00
static int tiff_uncompress ( uint8_t * dst , unsigned long * len , const uint8_t * src ,
int size )
2009-09-27 10:01:01 +03:00
{
2011-06-06 15:13:02 +03:00
z_stream zstream = { 0 } ;
2009-09-27 10:01:01 +03:00
int zret ;
2013-06-08 12:18:37 +03:00
zstream . next_in = ( uint8_t * ) src ;
2013-06-01 16:35:11 +03:00
zstream . avail_in = size ;
zstream . next_out = dst ;
2009-09-27 10:01:01 +03:00
zstream . avail_out = * len ;
2013-06-01 16:35:11 +03:00
zret = inflateInit ( & zstream ) ;
2009-09-27 10:01:01 +03:00
if ( zret ! = Z_OK ) {
av_log ( NULL , AV_LOG_ERROR , " Inflate init error: %d \n " , zret ) ;
return zret ;
}
zret = inflate ( & zstream , Z_SYNC_FLUSH ) ;
inflateEnd ( & zstream ) ;
* len = zstream . total_out ;
return zret = = Z_STREAM_END ? Z_OK : zret ;
}
2013-06-03 04:51:05 +03:00
2014-08-19 23:33:40 +03:00
static int tiff_unpack_zlib ( TiffContext * s , AVFrame * p , uint8_t * dst , int stride ,
const uint8_t * src , int size , int width , int lines ,
int strip_start , int is_yuv )
2013-06-03 04:51:05 +03:00
{
uint8_t * zbuf ;
unsigned long outlen ;
int ret , line ;
outlen = width * lines ;
zbuf = av_malloc ( outlen ) ;
if ( ! zbuf )
return AVERROR ( ENOMEM ) ;
2013-06-08 12:18:37 +03:00
if ( s - > fill_order ) {
if ( ( ret = deinvert_buffer ( s , src , size ) ) < 0 ) {
av_free ( zbuf ) ;
return ret ;
}
src = s - > deinvert_buf ;
}
2013-06-03 04:51:05 +03:00
ret = tiff_uncompress ( zbuf , & outlen , src , size ) ;
if ( ret ! = Z_OK ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
" Uncompressing failed (%lu of %lu) with error %d \n " , outlen ,
( unsigned long ) width * lines , ret ) ;
av_free ( zbuf ) ;
return AVERROR_UNKNOWN ;
}
src = zbuf ;
for ( line = 0 ; line < lines ; line + + ) {
2013-06-08 12:18:37 +03:00
if ( s - > bpp < 8 & & s - > avctx - > pix_fmt = = AV_PIX_FMT_PAL8 ) {
2018-10-30 23:05:52 +02:00
horizontal_fill ( s , s - > bpp , dst , 1 , src , 0 , width , 0 ) ;
2013-06-08 12:18:37 +03:00
} else {
memcpy ( dst , src , width ) ;
}
2014-08-19 23:33:40 +03:00
if ( is_yuv ) {
unpack_yuv ( s , p , dst , strip_start + line ) ;
line + = s - > subsampling [ 1 ] - 1 ;
}
2013-06-03 04:51:05 +03:00
dst + = stride ;
src + = width ;
}
av_free ( zbuf ) ;
return 0 ;
}
2009-09-27 12:43:11 +03:00
# endif
2009-09-27 10:01:01 +03:00
2014-08-23 05:39:57 +03:00
# if CONFIG_LZMA
static int tiff_uncompress_lzma ( uint8_t * dst , uint64_t * len , const uint8_t * src ,
int size )
{
lzma_stream stream = LZMA_STREAM_INIT ;
lzma_ret ret ;
stream . next_in = ( uint8_t * ) src ;
stream . avail_in = size ;
stream . next_out = dst ;
stream . avail_out = * len ;
ret = lzma_stream_decoder ( & stream , UINT64_MAX , 0 ) ;
if ( ret ! = LZMA_OK ) {
av_log ( NULL , AV_LOG_ERROR , " LZMA init error: %d \n " , ret ) ;
return ret ;
}
ret = lzma_code ( & stream , LZMA_RUN ) ;
lzma_end ( & stream ) ;
* len = stream . total_out ;
return ret = = LZMA_STREAM_END ? LZMA_OK : ret ;
}
static int tiff_unpack_lzma ( TiffContext * s , AVFrame * p , uint8_t * dst , int stride ,
const uint8_t * src , int size , int width , int lines ,
int strip_start , int is_yuv )
{
2017-01-08 17:37:56 +02:00
uint64_t outlen = width * ( uint64_t ) lines ;
2014-08-23 05:39:57 +03:00
int ret , line ;
uint8_t * buf = av_malloc ( outlen ) ;
if ( ! buf )
return AVERROR ( ENOMEM ) ;
if ( s - > fill_order ) {
if ( ( ret = deinvert_buffer ( s , src , size ) ) < 0 ) {
av_free ( buf ) ;
return ret ;
}
src = s - > deinvert_buf ;
}
ret = tiff_uncompress_lzma ( buf , & outlen , src , size ) ;
if ( ret ! = LZMA_OK ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
" Uncompressing failed (% " PRIu64 " of % " PRIu64 " ) with error %d \n " , outlen ,
( uint64_t ) width * lines , ret ) ;
av_free ( buf ) ;
return AVERROR_UNKNOWN ;
}
src = buf ;
for ( line = 0 ; line < lines ; line + + ) {
if ( s - > bpp < 8 & & s - > avctx - > pix_fmt = = AV_PIX_FMT_PAL8 ) {
2018-10-30 23:05:52 +02:00
horizontal_fill ( s , s - > bpp , dst , 1 , src , 0 , width , 0 ) ;
2014-08-23 05:39:57 +03:00
} else {
memcpy ( dst , src , width ) ;
}
if ( is_yuv ) {
unpack_yuv ( s , p , dst , strip_start + line ) ;
line + = s - > subsampling [ 1 ] - 1 ;
}
dst + = stride ;
src + = width ;
}
av_free ( buf ) ;
return 0 ;
}
# endif
2013-06-03 04:58:17 +03:00
static int tiff_unpack_fax ( TiffContext * s , uint8_t * dst , int stride ,
2013-06-08 12:31:31 +03:00
const uint8_t * src , int size , int width , int lines )
2013-06-03 04:58:17 +03:00
{
int i , ret = 0 ;
2013-06-08 12:31:31 +03:00
int line ;
2017-06-03 23:57:58 +02:00
uint8_t * src2 ;
av_fast_padded_malloc ( & s - > fax_buffer , & s - > fax_buffer_size , size ) ;
src2 = s - > fax_buffer ;
2013-06-03 04:58:17 +03:00
if ( ! src2 ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
" Error allocating temporary buffer \n " ) ;
return AVERROR ( ENOMEM ) ;
}
2015-08-13 17:02:05 +02:00
2013-06-03 04:58:17 +03:00
if ( ! s - > fill_order ) {
memcpy ( src2 , src , size ) ;
} else {
for ( i = 0 ; i < size ; i + + )
src2 [ i ] = ff_reverse [ src [ i ] ] ;
}
2015-06-29 23:48:34 +02:00
memset ( src2 + size , 0 , AV_INPUT_BUFFER_PADDING_SIZE ) ;
2013-06-03 04:58:17 +03:00
ret = ff_ccitt_unpack ( s - > avctx , src2 , size , dst , lines , stride ,
s - > compr , s - > fax_opts ) ;
2013-06-08 12:31:31 +03:00
if ( s - > bpp < 8 & & s - > avctx - > pix_fmt = = AV_PIX_FMT_PAL8 )
for ( line = 0 ; line < lines ; line + + ) {
2018-10-30 23:05:52 +02:00
horizontal_fill ( s , s - > bpp , dst , 1 , dst , 0 , width , 0 ) ;
2013-06-08 12:31:31 +03:00
dst + = stride ;
}
2013-06-03 04:58:17 +03:00
return ret ;
}
2019-08-29 15:10:52 +02:00
static int dng_decode_strip ( AVCodecContext * avctx , AVFrame * frame ) ;
2014-04-27 20:52:37 +03:00
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 )
2012-04-13 04:28:37 +03:00
{
2013-09-30 02:47:55 +03:00
PutByteContext pb ;
2012-11-17 15:40:37 +03:00
int c , line , pixels , code , ret ;
2008-02-01 16:28:22 +02:00
const uint8_t * ssrc = src ;
2013-09-30 02:47:55 +03:00
int width = ( ( s - > width * s - > bpp ) + 7 ) > > 3 ;
2014-08-19 21:57:42 +03:00
const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get ( p - > format ) ;
2014-08-24 02:54:45 +03:00
int is_yuv = ! ( desc - > flags & AV_PIX_FMT_FLAG_RGB ) & &
( desc - > flags & AV_PIX_FMT_FLAG_PLANAR ) & &
desc - > nb_components > = 3 ;
2019-08-29 15:10:43 +02:00
int is_dng ;
2006-10-13 13:48:29 +03:00
2013-05-09 22:39:32 +03:00
if ( s - > planar )
width / = s - > bppcount ;
2012-04-13 04:22:07 +03:00
if ( size < = 0 )
return AVERROR_INVALIDDATA ;
2014-04-27 20:52:37 +03:00
if ( is_yuv ) {
int bytes_per_row = ( ( ( s - > width - 1 ) / s - > subsampling [ 0 ] + 1 ) * s - > bpp *
s - > subsampling [ 0 ] * s - > subsampling [ 1 ] + 7 ) > > 3 ;
av_fast_padded_malloc ( & s - > yuv_line , & s - > yuv_line_size , bytes_per_row ) ;
if ( s - > yuv_line = = NULL ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Not enough memory \n " ) ;
return AVERROR ( ENOMEM ) ;
}
dst = s - > yuv_line ;
stride = 0 ;
2014-09-15 02:33:09 +03:00
width = ( s - > width - 1 ) / s - > subsampling [ 0 ] + 1 ;
width = width * s - > subsampling [ 0 ] * s - > subsampling [ 1 ] + 2 * width ;
2014-04-27 20:52:37 +03:00
av_assert0 ( width < = bytes_per_row ) ;
av_assert0 ( s - > bpp = = 24 ) ;
}
2018-10-30 23:05:52 +02:00
if ( s - > is_bayer ) {
width = ( s - > bpp * s - > width + 7 ) > > 3 ;
}
2018-12-14 18:32:25 +02:00
if ( p - > format = = AV_PIX_FMT_GRAY12 ) {
av_fast_padded_malloc ( & s - > yuv_line , & s - > yuv_line_size , width ) ;
if ( s - > yuv_line = = NULL ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Not enough memory \n " ) ;
return AVERROR ( ENOMEM ) ;
}
dst = s - > yuv_line ;
stride = 0 ;
}
2014-04-27 20:52:37 +03:00
2012-04-13 04:28:37 +03:00
if ( s - > compr = = TIFF_DEFLATE | | s - > compr = = TIFF_ADOBE_DEFLATE ) {
2013-06-03 04:51:05 +03:00
# if CONFIG_ZLIB
2014-08-19 23:33:40 +03:00
return tiff_unpack_zlib ( s , p , dst , stride , src , size , width , lines ,
strip_start , is_yuv ) ;
2013-06-03 04:51:05 +03:00
# else
av_log ( s - > avctx , AV_LOG_ERROR ,
" zlib support not enabled, "
" deflate compression not supported \n " ) ;
return AVERROR ( ENOSYS ) ;
2014-08-23 05:39:57 +03:00
# endif
}
if ( s - > compr = = TIFF_LZMA ) {
# if CONFIG_LZMA
return tiff_unpack_lzma ( s , p , dst , stride , src , size , width , lines ,
strip_start , is_yuv ) ;
# else
av_log ( s - > avctx , AV_LOG_ERROR ,
" LZMA support not enabled \n " ) ;
return AVERROR ( ENOSYS ) ;
2006-10-13 13:48:29 +03:00
# endif
2013-06-03 04:51:05 +03:00
}
2012-04-13 04:28:37 +03:00
if ( s - > compr = = TIFF_LZW ) {
2012-12-20 18:36:44 +03:00
if ( s - > fill_order ) {
2013-05-28 20:13:26 +03:00
if ( ( ret = deinvert_buffer ( s , src , size ) ) < 0 )
return ret ;
ssrc = src = s - > deinvert_buf ;
2012-12-20 18:36:44 +03:00
}
2013-01-03 06:25:55 +03:00
if ( size > 1 & & ! src [ 0 ] & & ( src [ 1 ] & 1 ) ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Old style LZW is unsupported \n " ) ;
}
2012-11-17 15:40:37 +03:00
if ( ( ret = ff_lzw_decode_init ( s - > lzw , 8 , src , size , FF_LZW_TIFF ) ) < 0 ) {
2006-10-26 07:15:48 +03:00
av_log ( s - > avctx , AV_LOG_ERROR , " Error initializing LZW decoder \n " ) ;
2012-11-17 15:40:37 +03:00
return ret ;
2006-10-26 07:15:48 +03:00
}
2013-09-30 02:47:55 +03:00
for ( line = 0 ; line < lines ; line + + ) {
pixels = ff_lzw_decode ( s - > lzw , dst , width ) ;
if ( pixels < width ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Decoded only %i bytes of %i \n " ,
pixels , width ) ;
return AVERROR_INVALIDDATA ;
}
2014-04-13 04:01:03 +03:00
if ( s - > bpp < 8 & & s - > avctx - > pix_fmt = = AV_PIX_FMT_PAL8 )
2018-10-30 23:05:52 +02:00
horizontal_fill ( s , s - > bpp , dst , 1 , dst , 0 , width , 0 ) ;
2014-04-27 20:52:37 +03:00
if ( is_yuv ) {
unpack_yuv ( s , p , dst , strip_start + line ) ;
line + = s - > subsampling [ 1 ] - 1 ;
2018-12-14 18:32:25 +02:00
} else if ( p - > format = = AV_PIX_FMT_GRAY12 ) {
unpack_gray ( s , p , dst , strip_start + line , width , s - > bpp ) ;
2014-04-27 20:52:37 +03:00
}
2013-09-30 02:47:55 +03:00
dst + = stride ;
}
return 0 ;
2006-10-26 07:15:48 +03:00
}
2013-06-01 16:35:11 +03:00
if ( s - > compr = = TIFF_CCITT_RLE | |
s - > compr = = TIFF_G3 | |
s - > compr = = TIFF_G4 ) {
2019-01-12 20:37:18 +02:00
if ( is_yuv | | p - > format = = AV_PIX_FMT_GRAY12 )
2014-04-27 20:52:37 +03:00
return AVERROR_INVALIDDATA ;
2013-06-08 12:31:31 +03:00
return tiff_unpack_fax ( s , dst , stride , src , size , width , lines ) ;
2008-12-26 20:42:26 +02:00
}
2013-09-30 02:47:55 +03:00
bytestream2_init ( & s - > gb , src , size ) ;
2014-04-27 20:52:37 +03:00
bytestream2_init_writer ( & pb , dst , is_yuv ? s - > yuv_line_size : ( stride * lines ) ) ;
2013-09-30 02:47:55 +03:00
2019-08-29 15:10:43 +02:00
is_dng = ( s - > tiff_type = = TIFF_TYPE_DNG | | s - > tiff_type = = TIFF_TYPE_CINEMADNG ) ;
2019-08-29 15:10:52 +02:00
/* 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 ;
}
2012-04-13 04:28:37 +03:00
for ( line = 0 ; line < lines ; line + + ) {
if ( src - ssrc > size ) {
2006-10-13 13:48:29 +03:00
av_log ( s - > avctx , AV_LOG_ERROR , " Source data overread \n " ) ;
2012-11-17 15:40:37 +03:00
return AVERROR_INVALIDDATA ;
2006-10-13 13:48:29 +03:00
}
2014-04-13 04:01:03 +03:00
2013-09-30 02:47:55 +03:00
if ( bytestream2_get_bytes_left ( & s - > gb ) = = 0 | | bytestream2_get_eof ( & pb ) )
break ;
bytestream2_seek_p ( & pb , stride * line , SEEK_SET ) ;
2012-04-13 04:28:37 +03:00
switch ( s - > compr ) {
2006-10-13 13:48:29 +03:00
case TIFF_RAW :
2011-10-01 01:45:03 +03:00
if ( ssrc + size - src < width )
return AVERROR_INVALIDDATA ;
2014-04-13 04:01:03 +03:00
2011-05-09 22:59:20 +03:00
if ( ! s - > fill_order ) {
2018-10-30 23:05:52 +02:00
horizontal_fill ( s , s - > bpp * ( s - > avctx - > pix_fmt = = AV_PIX_FMT_PAL8 | | s - > is_bayer ) ,
2011-12-31 22:45:04 +03:00
dst , 1 , src , 0 , width , 0 ) ;
2011-05-09 22:59:20 +03:00
} else {
int i ;
for ( i = 0 ; i < width ; i + + )
2012-10-11 19:50:30 +03:00
dst [ i ] = ff_reverse [ src [ i ] ] ;
2011-05-09 22:59:20 +03:00
}
2019-08-29 15:10:43 +02:00
/* Color processing for DNG images with uncompressed strips (non-tiled) */
if ( is_dng ) {
int is_u16 , pixel_size_bytes , pixel_size_bits ;
is_u16 = ( s - > bpp > 8 ) ;
pixel_size_bits = ( is_u16 ? 16 : 8 ) ;
pixel_size_bytes = ( is_u16 ? sizeof ( uint16_t ) : sizeof ( uint8_t ) ) ;
dng_blit ( s ,
dst ,
0 , // no stride, only 1 line
dst ,
0 , // no stride, only 1 line
width / pixel_size_bytes * pixel_size_bits / s - > bpp * s - > bppcount , // need to account for [1, 16] bpp
1 ,
2019-08-29 15:10:49 +02:00
0 , // single-component variation is only preset in JPEG-encoded DNGs
2019-08-29 15:10:43 +02:00
is_u16 ) ;
}
2008-12-22 08:39:31 +02:00
src + = width ;
2006-10-13 13:48:29 +03:00
break ;
case TIFF_PACKBITS :
2012-04-13 04:28:37 +03:00
for ( pixels = 0 ; pixels < width ; ) {
2012-04-15 21:19:42 +03:00
if ( ssrc + size - src < 2 ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Read went out of bounds \n " ) ;
return AVERROR_INVALIDDATA ;
}
2013-05-28 20:20:29 +03:00
code = s - > fill_order ? ( int8_t ) ff_reverse [ * src + + ] : ( int8_t ) * src + + ;
2012-04-13 04:28:37 +03:00
if ( code > = 0 ) {
2006-10-13 13:48:29 +03:00
code + + ;
2013-06-03 05:53:02 +03:00
if ( pixels + code > width | |
ssrc + size - src < code ) {
2012-04-13 04:28:37 +03:00
av_log ( s - > avctx , AV_LOG_ERROR ,
" Copy went out of bounds \n " ) ;
2012-11-17 15:40:37 +03:00
return AVERROR_INVALIDDATA ;
2006-10-13 13:48:29 +03:00
}
2018-10-30 23:05:52 +02:00
horizontal_fill ( s , s - > bpp * ( s - > avctx - > pix_fmt = = AV_PIX_FMT_PAL8 ) ,
2011-12-31 22:45:04 +03:00
dst , 1 , src , 0 , code , pixels ) ;
2013-06-01 16:35:11 +03:00
src + = code ;
2006-10-13 13:48:29 +03:00
pixels + = code ;
2012-04-13 04:28:37 +03:00
} else if ( code ! = - 128 ) { // -127..-1
2006-10-13 13:48:29 +03:00
code = ( - code ) + 1 ;
2012-04-13 04:28:37 +03:00
if ( pixels + code > width ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
" Run went out of bounds \n " ) ;
2012-11-17 15:40:37 +03:00
return AVERROR_INVALIDDATA ;
2006-10-13 13:48:29 +03:00
}
c = * src + + ;
2018-10-30 23:05:52 +02:00
horizontal_fill ( s , s - > bpp * ( s - > avctx - > pix_fmt = = AV_PIX_FMT_PAL8 ) ,
2011-12-31 22:45:04 +03:00
dst , 0 , NULL , c , code , pixels ) ;
2006-10-13 13:48:29 +03:00
pixels + = code ;
}
}
2013-05-28 20:20:29 +03:00
if ( s - > fill_order ) {
int i ;
for ( i = 0 ; i < width ; i + + )
dst [ i ] = ff_reverse [ dst [ i ] ] ;
}
2006-10-13 13:48:29 +03:00
break ;
}
2014-04-27 20:52:37 +03:00
if ( is_yuv ) {
unpack_yuv ( s , p , dst , strip_start + line ) ;
line + = s - > subsampling [ 1 ] - 1 ;
2018-12-14 18:32:25 +02:00
} else if ( p - > format = = AV_PIX_FMT_GRAY12 ) {
unpack_gray ( s , p , dst , strip_start + line , width , s - > bpp ) ;
2014-04-27 20:52:37 +03:00
}
2006-10-13 13:48:29 +03:00
dst + = stride ;
}
return 0 ;
}
2019-08-29 15:10:41 +02:00
/**
2019-08-29 15:10:42 +02:00
* Map stored raw sensor values into linear reference values ( see : DNG Specification - Chapter 5 )
2019-08-29 15:10:41 +02:00
*/
2019-08-29 15:10:42 +02:00
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 ;
2019-08-29 15:10:41 +02:00
// Lookup table lookup
if ( lut )
value = lut [ value ] ;
// Black level subtraction
value = av_clip_uint16_c ( ( unsigned ) value - black_level ) ;
// Color scaling
2019-08-29 15:10:42 +02:00
value_norm = ( float ) value * scale_factor ;
2019-08-31 20:57:29 +02:00
value = av_clip_uint16_c ( value_norm * 65535 ) ;
2019-08-29 15:10:41 +02:00
return value ;
}
2019-08-29 15:10:42 +02:00
static uint16_t av_always_inline dng_process_color8 ( uint16_t value ,
2019-08-29 15:10:41 +02:00
const uint16_t * lut ,
uint16_t black_level ,
float scale_factor ) {
2019-08-29 15:10:42 +02:00
return dng_process_color16 ( value , lut , black_level , scale_factor ) > > 8 ;
2019-08-29 15:10:41 +02:00
}
static void dng_blit ( TiffContext * s , uint8_t * dst , int dst_stride ,
const uint8_t * src , int src_stride ,
2019-08-29 15:10:49 +02:00
int width , int height , int is_single_comp , int is_u16 )
2019-08-29 15:10:41 +02:00
{
int line , col ;
float scale_factor ;
scale_factor = 1.0f / ( s - > white_level - s - > black_level ) ;
2019-08-29 15:10:49 +02:00
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 + + ) {
2019-08-29 15:10:41 +02:00
uint16_t * dst_u16 = ( uint16_t * ) dst ;
uint16_t * src_u16 = ( uint16_t * ) src ;
2019-08-29 15:10:49 +02:00
/* 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 */
2019-08-29 15:10:41 +02:00
for ( col = 0 ; col < width ; col + + )
2019-08-29 15:10:42 +02:00
* dst_u16 + + = dng_process_color16 ( * src_u16 + + , s - > dng_lut , s - > black_level , scale_factor ) ;
2019-08-29 15:10:41 +02:00
dst + = dst_stride * sizeof ( uint16_t ) ;
src + = src_stride * sizeof ( uint16_t ) ;
}
} else {
2019-08-29 15:10:49 +02:00
/* 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 + + ) {
for ( col = 0 ; col < width ; col + + )
* dst + + = dng_process_color8 ( * src + + , s - > dng_lut , s - > black_level , scale_factor ) ;
2019-08-29 15:10:41 +02:00
2019-08-29 15:10:49 +02:00
dst + = dst_stride ;
src + = src_stride ;
}
2019-08-29 15:10:41 +02:00
}
}
}
2019-08-29 15:10:52 +02:00
static int dng_decode_jpeg ( AVCodecContext * avctx , AVFrame * frame ,
int tile_byte_count , int dst_x , int dst_y , int w , int h )
2019-08-29 15:10:41 +02:00
{
TiffContext * s = avctx - > priv_data ;
AVPacket jpkt ;
uint8_t * dst_data , * src_data ;
uint32_t dst_offset ; /* offset from dst buffer in pixels */
2019-08-29 15:10:49 +02:00
int is_single_comp , is_u16 , pixel_size ;
2019-08-29 15:10:41 +02:00
int ret ;
/* Prepare a packet and send to the MJPEG decoder */
av_init_packet ( & jpkt ) ;
jpkt . data = ( uint8_t * ) s - > gb . buffer ;
jpkt . size = tile_byte_count ;
2019-08-29 15:10:48 +02:00
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 ;
}
2019-08-29 15:10:41 +02:00
ret = avcodec_send_packet ( s - > avctx_mjpeg , & 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 ;
}
/* Copy the outputted tile's pixels from 'jpgframe' to 'frame' (final buffer) */
2019-08-29 15:10:49 +02:00
/* See dng_blit for explanation */
is_single_comp = ( s - > avctx_mjpeg - > width = = w * 2 & & s - > avctx_mjpeg - > height = = h / 2 ) ;
2019-08-29 15:10:41 +02:00
is_u16 = ( s - > bpp > 8 ) ;
pixel_size = ( is_u16 ? sizeof ( uint16_t ) : sizeof ( uint8_t ) ) ;
2019-08-29 15:10:49 +02:00
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 ;
}
2019-08-29 15:10:52 +02:00
dst_offset = dst_x + frame - > linesize [ 0 ] * dst_y / pixel_size ;
2019-08-29 15:10:41 +02:00
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 ,
2019-08-29 15:10:49 +02:00
is_single_comp ,
2019-08-29 15:10:41 +02:00
is_u16 ) ;
av_frame_unref ( s - > jpgframe ) ;
return 0 ;
}
2019-08-29 15:10:52 +02:00
static int dng_decode_tiles ( AVCodecContext * avctx , AVFrame * frame , AVPacket * avpkt )
2019-08-29 15:10:41 +02:00
{
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 ;
2019-08-29 15:10:45 +02:00
int has_width_leftover , has_height_leftover ;
2019-08-29 15:10:41 +02:00
int tile_x = 0 , tile_y = 0 ;
int pos_x = 0 , pos_y = 0 ;
int ret ;
2019-08-29 15:10:52 +02:00
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 ;
2019-08-29 15:10:45 +02:00
has_width_leftover = ( s - > width % s - > tile_width ! = 0 ) ;
has_height_leftover = ( s - > height % s - > tile_length ! = 0 ) ;
2019-08-29 15:10:41 +02:00
/* 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 ;
2019-08-29 15:10:45 +02:00
if ( has_width_leftover & & tile_x = = tile_count_x - 1 ) // If on the right-most tile
2019-08-29 15:10:41 +02:00
tile_width = s - > width % s - > tile_width ;
else
tile_width = s - > tile_width ;
2019-08-29 15:10:45 +02:00
if ( has_height_leftover & & tile_y = = tile_count_y - 1 ) // If on the bottom-most tile
2019-08-29 15:10:41 +02:00
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 */
2019-08-29 15:10:52 +02:00
ret = dng_decode_jpeg ( avctx , frame , tile_byte_count , pos_x , pos_y , tile_width , tile_length ) ;
2019-08-29 15:10:41 +02:00
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 ;
}
}
2019-08-29 15:10:52 +02:00
/* Frame is ready to be output */
frame - > pict_type = AV_PICTURE_TYPE_I ;
frame - > key_frame = 1 ;
2019-08-29 15:10:41 +02:00
2019-08-29 15:10:52 +02:00
return avpkt - > size ;
}
2019-08-29 15:10:41 +02:00
2019-08-29 15:10:52 +02:00
static int dng_decode_strip ( AVCodecContext * avctx , AVFrame * frame )
{
2019-08-29 15:10:41 +02:00
TiffContext * s = avctx - > priv_data ;
2019-08-29 15:10:52 +02:00
s - > jpgframe - > width = s - > width ;
s - > jpgframe - > height = s - > height ;
2019-08-29 15:10:41 +02:00
2019-08-29 15:10:52 +02:00
s - > avctx_mjpeg - > width = s - > width ;
s - > avctx_mjpeg - > height = s - > height ;
2019-08-29 15:10:41 +02:00
2019-08-29 15:10:52 +02:00
return dng_decode_jpeg ( avctx , frame , s - > stripsize , 0 , 0 , s - > width , s - > height ) ;
2019-08-29 15:10:41 +02:00
}
2013-08-09 17:01:46 +03:00
static int init_image ( TiffContext * s , ThreadFrame * frame )
2011-05-09 13:51:24 +03:00
{
2014-08-09 16:19:45 +03:00
int ret ;
2014-09-05 12:15:13 +03:00
int create_gray_palette = 0 ;
2011-05-09 13:51:24 +03:00
2015-03-07 23:06:59 +02:00
// make sure there is no aliasing in the following switch
if ( s - > bpp > = 100 | | s - > bppcount > = 10 ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
" Unsupported image parameters: bpp=%d, bppcount=%d \n " ,
s - > bpp , s - > bppcount ) ;
return AVERROR_INVALIDDATA ;
}
2018-10-30 23:05:52 +02:00
switch ( s - > planar * 1000 + s - > bpp * 10 + s - > bppcount + s - > is_bayer * 10000 ) {
2011-05-09 13:51:24 +03:00
case 11 :
2011-12-31 06:49:33 +03:00
if ( ! s - > palette_is_set ) {
2012-10-08 21:54:00 +03:00
s - > avctx - > pix_fmt = AV_PIX_FMT_MONOBLACK ;
2011-12-31 06:49:33 +03:00
break ;
}
2011-08-23 21:38:43 +03:00
case 21 :
case 41 :
2014-09-05 12:15:13 +03:00
s - > avctx - > pix_fmt = AV_PIX_FMT_PAL8 ;
if ( ! s - > palette_is_set ) {
create_gray_palette = 1 ;
}
break ;
2011-05-09 13:51:24 +03:00
case 81 :
2014-08-09 16:19:45 +03:00
s - > avctx - > pix_fmt = s - > palette_is_set ? AV_PIX_FMT_PAL8 : AV_PIX_FMT_GRAY8 ;
2011-05-09 13:51:24 +03:00
break ;
2018-12-14 18:32:25 +02:00
case 121 :
s - > avctx - > pix_fmt = AV_PIX_FMT_GRAY12 ;
break ;
2018-10-30 23:05:52 +02:00
case 10081 :
2018-11-26 03:57:32 +02:00
switch ( AV_RL32 ( s - > pattern ) ) {
2018-10-30 23:05:52 +02:00
case 0x02010100 :
s - > avctx - > pix_fmt = AV_PIX_FMT_BAYER_RGGB8 ;
break ;
case 0x00010102 :
s - > avctx - > pix_fmt = AV_PIX_FMT_BAYER_BGGR8 ;
break ;
case 0x01000201 :
s - > avctx - > pix_fmt = AV_PIX_FMT_BAYER_GBRG8 ;
break ;
case 0x01020001 :
s - > avctx - > pix_fmt = AV_PIX_FMT_BAYER_GRBG8 ;
break ;
default :
av_log ( s - > avctx , AV_LOG_ERROR , " Unsupported Bayer pattern: 0x%X \n " ,
2018-11-26 03:57:32 +02:00
AV_RL32 ( s - > pattern ) ) ;
2018-10-30 23:05:52 +02:00
return AVERROR_PATCHWELCOME ;
}
break ;
2019-08-29 15:10:50 +02:00
case 10101 :
2018-10-30 23:05:52 +02:00
case 10121 :
2019-08-29 15:10:50 +02:00
case 10141 :
2018-10-30 23:05:52 +02:00
case 10161 :
2018-11-26 03:57:32 +02:00
switch ( AV_RL32 ( s - > pattern ) ) {
2018-10-30 23:05:52 +02:00
case 0x02010100 :
2019-08-31 21:14:28 +02:00
s - > avctx - > pix_fmt = AV_PIX_FMT_BAYER_RGGB16 ;
2018-10-30 23:05:52 +02:00
break ;
case 0x00010102 :
2019-08-31 21:14:28 +02:00
s - > avctx - > pix_fmt = AV_PIX_FMT_BAYER_BGGR16 ;
2018-10-30 23:05:52 +02:00
break ;
case 0x01000201 :
2019-08-31 21:14:28 +02:00
s - > avctx - > pix_fmt = AV_PIX_FMT_BAYER_GBRG16 ;
2018-10-30 23:05:52 +02:00
break ;
case 0x01020001 :
2019-08-31 21:14:28 +02:00
s - > avctx - > pix_fmt = AV_PIX_FMT_BAYER_GRBG16 ;
2018-10-30 23:05:52 +02:00
break ;
default :
av_log ( s - > avctx , AV_LOG_ERROR , " Unsupported Bayer pattern: 0x%X \n " ,
2018-11-26 03:57:32 +02:00
AV_RL32 ( s - > pattern ) ) ;
2018-10-30 23:05:52 +02:00
return AVERROR_PATCHWELCOME ;
}
break ;
2011-05-09 13:51:24 +03:00
case 243 :
2014-04-27 20:52:37 +03:00
if ( s - > photometric = = TIFF_PHOTOMETRIC_YCBCR ) {
if ( s - > subsampling [ 0 ] = = 1 & & s - > subsampling [ 1 ] = = 1 ) {
s - > avctx - > pix_fmt = AV_PIX_FMT_YUV444P ;
2014-04-29 19:39:24 +03:00
} else if ( s - > subsampling [ 0 ] = = 2 & & s - > subsampling [ 1 ] = = 1 ) {
s - > avctx - > pix_fmt = AV_PIX_FMT_YUV422P ;
} else if ( s - > subsampling [ 0 ] = = 4 & & s - > subsampling [ 1 ] = = 1 ) {
s - > avctx - > pix_fmt = AV_PIX_FMT_YUV411P ;
2014-04-30 18:41:31 +03:00
} else if ( s - > subsampling [ 0 ] = = 1 & & s - > subsampling [ 1 ] = = 2 ) {
s - > avctx - > pix_fmt = AV_PIX_FMT_YUV440P ;
2014-04-27 20:52:37 +03:00
} else if ( s - > subsampling [ 0 ] = = 2 & & s - > subsampling [ 1 ] = = 2 ) {
s - > avctx - > pix_fmt = AV_PIX_FMT_YUV420P ;
2014-04-30 18:41:31 +03:00
} else if ( s - > subsampling [ 0 ] = = 4 & & s - > subsampling [ 1 ] = = 4 ) {
s - > avctx - > pix_fmt = AV_PIX_FMT_YUV410P ;
2014-04-27 20:52:37 +03:00
} else {
av_log ( s - > avctx , AV_LOG_ERROR , " Unsupported YCbCr subsampling \n " ) ;
return AVERROR_PATCHWELCOME ;
}
} else
s - > avctx - > pix_fmt = AV_PIX_FMT_RGB24 ;
2011-05-09 13:51:24 +03:00
break ;
case 161 :
2012-10-06 13:10:34 +03:00
s - > avctx - > pix_fmt = s - > le ? AV_PIX_FMT_GRAY16LE : AV_PIX_FMT_GRAY16BE ;
2011-05-09 13:51:24 +03:00
break ;
2012-01-22 06:49:46 +03:00
case 162 :
2014-07-20 09:34:19 +03:00
s - > avctx - > pix_fmt = AV_PIX_FMT_YA8 ;
2012-01-22 06:49:46 +03:00
break ;
2014-07-21 00:54:35 +03:00
case 322 :
s - > avctx - > pix_fmt = s - > le ? AV_PIX_FMT_YA16LE : AV_PIX_FMT_YA16BE ;
break ;
2011-05-09 13:51:24 +03:00
case 324 :
2019-01-12 18:27:48 +02:00
s - > avctx - > pix_fmt = s - > photometric = = TIFF_PHOTOMETRIC_SEPARATED ? AV_PIX_FMT_RGB0 : AV_PIX_FMT_RGBA ;
2011-05-09 13:51:24 +03:00
break ;
2019-03-20 18:50:25 +02:00
case 405 :
if ( s - > photometric = = TIFF_PHOTOMETRIC_SEPARATED )
s - > avctx - > pix_fmt = AV_PIX_FMT_RGBA ;
2019-03-23 19:28:10 +02:00
else {
av_log ( s - > avctx , AV_LOG_ERROR ,
" bpp=40 without PHOTOMETRIC_SEPARATED is unsupported \n " ) ;
return AVERROR_PATCHWELCOME ;
}
2019-03-20 18:50:25 +02:00
break ;
2011-05-09 13:51:24 +03:00
case 483 :
2013-06-07 00:42:02 +03:00
s - > avctx - > pix_fmt = s - > le ? AV_PIX_FMT_RGB48LE : AV_PIX_FMT_RGB48BE ;
2011-05-09 13:51:24 +03:00
break ;
2012-01-14 03:10:13 +03:00
case 644 :
2013-06-07 00:42:02 +03:00
s - > avctx - > pix_fmt = s - > le ? AV_PIX_FMT_RGBA64LE : AV_PIX_FMT_RGBA64BE ;
break ;
case 1243 :
s - > avctx - > pix_fmt = AV_PIX_FMT_GBRP ;
break ;
case 1324 :
s - > avctx - > pix_fmt = AV_PIX_FMT_GBRAP ;
break ;
case 1483 :
s - > avctx - > pix_fmt = s - > le ? AV_PIX_FMT_GBRP16LE : AV_PIX_FMT_GBRP16BE ;
break ;
case 1644 :
s - > avctx - > pix_fmt = s - > le ? AV_PIX_FMT_GBRAP16LE : AV_PIX_FMT_GBRAP16BE ;
2012-01-14 03:10:13 +03:00
break ;
2011-05-09 13:51:24 +03:00
default :
av_log ( s - > avctx , AV_LOG_ERROR ,
" This format is not supported (bpp=%d, bppcount=%d) \n " ,
s - > bpp , s - > bppcount ) ;
return AVERROR_INVALIDDATA ;
}
2014-08-19 22:08:34 +03:00
if ( s - > photometric = = TIFF_PHOTOMETRIC_YCBCR ) {
const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get ( s - > avctx - > pix_fmt ) ;
2014-08-24 02:54:45 +03:00
if ( ( desc - > flags & AV_PIX_FMT_FLAG_RGB ) | |
! ( desc - > flags & AV_PIX_FMT_FLAG_PLANAR ) | |
desc - > nb_components < 3 ) {
2014-08-19 22:08:34 +03:00
av_log ( s - > avctx , AV_LOG_ERROR , " Unsupported YCbCr variant \n " ) ;
return AVERROR_INVALIDDATA ;
}
}
2011-05-09 13:51:24 +03:00
if ( s - > width ! = s - > avctx - > width | | s - > height ! = s - > avctx - > height ) {
2013-10-27 12:02:26 +03:00
ret = ff_set_dimensions ( s - > avctx , s - > width , s - > height ) ;
if ( ret < 0 )
2011-05-09 13:51:24 +03:00
return ret ;
}
2013-08-09 17:01:46 +03:00
if ( ( ret = ff_thread_get_buffer ( s - > avctx , frame , 0 ) ) < 0 )
2011-05-09 13:51:24 +03:00
return ret ;
2012-10-06 13:10:34 +03:00
if ( s - > avctx - > pix_fmt = = AV_PIX_FMT_PAL8 ) {
2014-09-05 12:15:13 +03:00
if ( ! create_gray_palette )
memcpy ( frame - > f - > data [ 1 ] , s - > palette , sizeof ( s - > palette ) ) ;
else {
/* make default grayscale pal */
int i ;
uint32_t * pal = ( uint32_t * ) frame - > f - > data [ 1 ] ;
for ( i = 0 ; i < 1 < < s - > bpp ; i + + )
pal [ i ] = 0xFFU < < 24 | i * 255 / ( ( 1 < < s - > bpp ) - 1 ) * 0x010101 ;
}
2011-05-09 13:51:24 +03:00
}
return 0 ;
}
2006-10-13 13:48:29 +03:00
2014-04-07 11:39:55 +03:00
static void set_sar ( TiffContext * s , unsigned tag , unsigned num , unsigned den )
{
int offset = tag = = TIFF_YRES ? 2 : 0 ;
s - > res [ offset + + ] = num ;
s - > res [ offset ] = den ;
2016-12-13 01:43:21 +02:00
if ( s - > res [ 0 ] & & s - > res [ 1 ] & & s - > res [ 2 ] & & s - > res [ 3 ] ) {
uint64_t num = s - > res [ 2 ] * ( uint64_t ) s - > res [ 1 ] ;
uint64_t den = s - > res [ 0 ] * ( uint64_t ) s - > res [ 3 ] ;
if ( num > INT64_MAX | | den > INT64_MAX ) {
num = num > > 1 ;
den = den > > 1 ;
}
2014-04-07 11:39:55 +03:00
av_reduce ( & s - > avctx - > sample_aspect_ratio . num , & s - > avctx - > sample_aspect_ratio . den ,
2016-12-13 01:43:21 +02:00
num , den , INT32_MAX ) ;
if ( ! s - > avctx - > sample_aspect_ratio . den )
s - > avctx - > sample_aspect_ratio = ( AVRational ) { 0 , 1 } ;
}
2014-04-07 11:39:55 +03:00
}
2013-03-13 20:51:17 +03:00
static int tiff_decode_tag ( TiffContext * s , AVFrame * frame )
2006-10-13 13:48:29 +03:00
{
2019-08-29 15:10:41 +02:00
unsigned tag , type , count , off , value = 0 , value2 = 1 ; // value2 is a denominator so init. to 1
2013-09-30 02:47:55 +03:00
int i , start ;
2014-04-13 05:33:20 +03:00
int pos ;
2011-10-04 01:19:52 +03:00
int ret ;
double * dp ;
2006-10-13 13:48:29 +03:00
2013-08-12 20:32:40 +03:00
ret = ff_tread_tag ( & s - > gb , s - > le , & tag , & type , & count , & start ) ;
if ( ret < 0 ) {
2013-08-11 15:16:09 +03:00
goto end ;
2012-02-23 21:47:50 +03:00
}
2013-10-27 15:10:06 +03:00
off = bytestream2_tell ( & s - > gb ) ;
2012-04-13 04:28:37 +03:00
if ( count = = 1 ) {
switch ( type ) {
2006-10-13 13:48:29 +03:00
case TIFF_BYTE :
case TIFF_SHORT :
case TIFF_LONG :
2013-10-27 15:07:44 +03:00
value = ff_tget ( & s - > gb , type , s - > le ) ;
2006-10-13 13:48:29 +03:00
break ;
2014-04-07 11:39:55 +03:00
case TIFF_RATIONAL :
value = ff_tget ( & s - > gb , TIFF_LONG , s - > le ) ;
value2 = ff_tget ( & s - > gb , TIFF_LONG , s - > le ) ;
2019-10-26 17:01:16 +02:00
if ( ! value2 ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Invalid denominator in rational \n " ) ;
return AVERROR_INVALIDDATA ;
}
2014-04-07 11:39:55 +03:00
break ;
2008-12-17 19:39:35 +02:00
case TIFF_STRING :
2012-04-13 04:28:37 +03:00
if ( count < = 4 ) {
2008-12-17 19:39:35 +02:00
break ;
}
2006-10-13 13:48:29 +03:00
default :
2012-02-23 21:22:51 +03:00
value = UINT_MAX ;
2006-10-13 13:48:29 +03:00
}
}
2012-04-13 04:28:37 +03:00
switch ( tag ) {
2019-05-30 12:42:40 +02:00
case TIFF_SUBFILE :
s - > is_thumbnail = ( value ! = 0 ) ;
2019-08-28 15:46:40 +02:00
break ;
2006-10-13 13:48:29 +03:00
case TIFF_WIDTH :
s - > width = value ;
break ;
case TIFF_HEIGHT :
s - > height = value ;
break ;
case TIFF_BPP :
2019-03-20 18:50:25 +02:00
if ( count > 5U ) {
2012-04-13 04:28:37 +03:00
av_log ( s - > avctx , AV_LOG_ERROR ,
" This format is not supported (bpp=%d, %d components) \n " ,
2014-10-03 17:08:32 +03:00
value , count ) ;
2012-11-17 15:40:37 +03:00
return AVERROR_INVALIDDATA ;
2011-01-07 00:12:55 +02:00
}
2014-10-03 17:08:32 +03:00
s - > bppcount = count ;
2012-04-13 04:28:37 +03:00
if ( count = = 1 )
s - > bpp = value ;
else {
switch ( type ) {
2006-10-13 13:48:29 +03:00
case TIFF_BYTE :
case TIFF_SHORT :
case TIFF_LONG :
2006-11-13 07:28:55 +02:00
s - > bpp = 0 ;
2012-07-16 03:31:11 +03:00
if ( bytestream2_get_bytes_left ( & s - > gb ) < type_sizes [ type ] * count )
2013-01-07 03:24:32 +03:00
return AVERROR_INVALIDDATA ;
2012-07-16 03:31:11 +03:00
for ( i = 0 ; i < count ; i + + )
2013-08-12 20:32:40 +03:00
s - > bpp + = ff_tget ( & s - > gb , type , s - > le ) ;
2006-10-13 13:48:29 +03:00
break ;
default :
s - > bpp = - 1 ;
}
}
2011-05-09 13:51:24 +03:00
break ;
case TIFF_SAMPLES_PER_PIXEL :
if ( count ! = 1 ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
" Samples per pixel requires a single value, many provided \n " ) ;
return AVERROR_INVALIDDATA ;
2006-11-13 07:32:10 +02:00
}
2019-03-20 18:50:25 +02:00
if ( value > 5U ) {
2013-02-19 19:48:56 +03:00
av_log ( s - > avctx , AV_LOG_ERROR ,
" Samples per pixel %d is too large \n " , value ) ;
return AVERROR_INVALIDDATA ;
}
2011-05-09 13:51:24 +03:00
if ( s - > bppcount = = 1 )
s - > bpp * = value ;
s - > bppcount = value ;
2006-10-13 13:48:29 +03:00
break ;
case TIFF_COMPR :
2013-06-01 16:35:11 +03:00
s - > compr = value ;
2016-10-05 13:49:17 +02:00
av_log ( s - > avctx , AV_LOG_DEBUG , " compression: %d \n " , s - > compr ) ;
2008-12-22 08:50:18 +02:00
s - > predictor = 0 ;
2012-04-13 04:28:37 +03:00
switch ( s - > compr ) {
2006-10-13 13:48:29 +03:00
case TIFF_RAW :
case TIFF_PACKBITS :
2006-10-26 07:15:48 +03:00
case TIFF_LZW :
2008-12-26 20:42:26 +02:00
case TIFF_CCITT_RLE :
break ;
case TIFF_G3 :
case TIFF_G4 :
s - > fax_opts = 0 ;
2006-10-13 13:48:29 +03:00
break ;
case TIFF_DEFLATE :
case TIFF_ADOBE_DEFLATE :
2009-01-14 01:44:16 +02:00
# if CONFIG_ZLIB
2006-10-13 13:48:29 +03:00
break ;
# else
av_log ( s - > avctx , AV_LOG_ERROR , " Deflate: ZLib not compiled in \n " ) ;
2012-11-17 15:40:37 +03:00
return AVERROR ( ENOSYS ) ;
2006-10-13 13:48:29 +03:00
# endif
2006-11-13 07:29:45 +02:00
case TIFF_JPEG :
case TIFF_NEWJPEG :
2019-08-29 15:10:41 +02:00
s - > is_jpeg = 1 ;
break ;
2014-08-18 11:27:49 +03:00
case TIFF_LZMA :
2014-08-23 05:39:57 +03:00
# if CONFIG_LZMA
break ;
# else
av_log ( s - > avctx , AV_LOG_ERROR , " LZMA not compiled in \n " ) ;
return AVERROR ( ENOSYS ) ;
# endif
2006-10-13 13:48:29 +03:00
default :
2012-04-13 04:28:37 +03:00
av_log ( s - > avctx , AV_LOG_ERROR , " Unknown compression method %i \n " ,
s - > compr ) ;
2012-11-17 15:40:37 +03:00
return AVERROR_INVALIDDATA ;
2006-10-13 13:48:29 +03:00
}
break ;
case TIFF_ROWSPERSTRIP :
2013-09-30 07:11:12 +03:00
if ( ! value | | ( type = = TIFF_LONG & & value = = UINT_MAX ) )
2013-01-06 03:56:23 +03:00
value = s - > height ;
2013-09-30 07:11:12 +03:00
s - > rps = FFMIN ( value , s - > height ) ;
2006-10-13 13:48:29 +03:00
break ;
case TIFF_STRIP_OFFS :
2012-04-13 04:28:37 +03:00
if ( count = = 1 ) {
2017-03-16 03:00:17 +02:00
if ( value > INT_MAX ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
" strippos %u too large \n " , value ) ;
return AVERROR_INVALIDDATA ;
}
2013-09-30 02:47:55 +03:00
s - > strippos = 0 ;
s - > stripoff = value ;
2012-04-13 04:28:37 +03:00
} else
2012-07-15 23:58:13 +03:00
s - > strippos = off ;
2006-10-13 13:48:29 +03:00
s - > strips = count ;
2012-04-13 04:28:37 +03:00
if ( s - > strips = = 1 )
s - > rps = s - > height ;
2006-10-13 13:48:29 +03:00
s - > sot = type ;
break ;
case TIFF_STRIP_SIZE :
2012-04-13 04:28:37 +03:00
if ( count = = 1 ) {
2017-03-16 03:00:17 +02:00
if ( value > INT_MAX ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
" stripsize %u too large \n " , value ) ;
return AVERROR_INVALIDDATA ;
}
2012-07-15 23:58:13 +03:00
s - > stripsizesoff = 0 ;
2013-09-30 02:47:55 +03:00
s - > stripsize = value ;
s - > strips = 1 ;
2012-04-13 04:28:37 +03:00
} else {
2012-07-15 23:58:13 +03:00
s - > stripsizesoff = off ;
2006-10-13 13:48:29 +03:00
}
s - > strips = count ;
2008-12-22 08:50:18 +02:00
s - > sstype = type ;
2006-10-13 13:48:29 +03:00
break ;
2014-04-07 11:39:55 +03:00
case TIFF_XRES :
case TIFF_YRES :
set_sar ( s , tag , value , value2 ) ;
break ;
2019-08-29 15:10:41 +02:00
case TIFF_TILE_OFFSETS :
s - > tile_offsets_offset = off ;
s - > tile_count = count ;
s - > is_tiled = 1 ;
break ;
2012-01-10 21:45:44 +03:00
case TIFF_TILE_BYTE_COUNTS :
2019-08-29 15:10:41 +02:00
s - > tile_byte_counts_offset = off ;
break ;
2012-01-10 21:45:44 +03:00
case TIFF_TILE_LENGTH :
2019-08-29 15:10:41 +02:00
s - > tile_length = value ;
break ;
2012-01-10 21:45:44 +03:00
case TIFF_TILE_WIDTH :
2019-08-29 15:10:41 +02:00
s - > tile_width = value ;
2012-01-10 21:45:44 +03:00
break ;
2006-10-13 13:48:29 +03:00
case TIFF_PREDICTOR :
2008-12-22 08:50:18 +02:00
s - > predictor = value ;
2006-10-13 13:48:29 +03:00
break ;
2018-10-30 23:05:52 +02:00
case TIFF_SUB_IFDS :
2019-05-30 12:42:41 +02:00
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 */
2018-10-30 23:05:52 +02:00
break ;
2019-08-31 21:14:28 +02:00
case DNG_LINEARIZATION_TABLE :
for ( int i = 0 ; i < FFMIN ( count , 1 < < s - > bpp ) ; i + + )
s - > dng_lut [ i ] = ff_tget ( & s - > gb , type , s - > le ) ;
2019-08-29 15:10:41 +02:00
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 ) ;
2019-10-26 17:01:16 +02:00
if ( ! value2 ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Invalid black level denominator \n " ) ;
return AVERROR_INVALIDDATA ;
}
2019-08-29 15:10:41 +02:00
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 ;
2019-05-30 12:42:42 +02:00
case DNG_WHITE_LEVEL :
2018-10-30 23:05:52 +02:00
s - > white_level = value ;
break ;
case TIFF_CFA_PATTERN_DIM :
if ( count ! = 2 | | ( ff_tget ( & s - > gb , type , s - > le ) ! = 2 & &
ff_tget ( & s - > gb , type , s - > le ) ! = 2 ) ) {
av_log ( s - > avctx , AV_LOG_ERROR , " CFA Pattern dimensions are not 2x2 \n " ) ;
return AVERROR_INVALIDDATA ;
}
break ;
case TIFF_CFA_PATTERN :
s - > is_bayer = 1 ;
s - > pattern [ 0 ] = ff_tget ( & s - > gb , type , s - > le ) ;
s - > pattern [ 1 ] = ff_tget ( & s - > gb , type , s - > le ) ;
s - > pattern [ 2 ] = ff_tget ( & s - > gb , type , s - > le ) ;
s - > pattern [ 3 ] = ff_tget ( & s - > gb , type , s - > le ) ;
break ;
2013-09-30 07:39:51 +03:00
case TIFF_PHOTOMETRIC :
2012-04-13 04:28:37 +03:00
switch ( value ) {
2013-09-30 07:39:51 +03:00
case TIFF_PHOTOMETRIC_WHITE_IS_ZERO :
case TIFF_PHOTOMETRIC_BLACK_IS_ZERO :
case TIFF_PHOTOMETRIC_RGB :
case TIFF_PHOTOMETRIC_PALETTE :
2019-01-12 18:27:48 +02:00
case TIFF_PHOTOMETRIC_SEPARATED :
2014-04-27 20:52:37 +03:00
case TIFF_PHOTOMETRIC_YCBCR :
2018-10-30 23:05:52 +02:00
case TIFF_PHOTOMETRIC_CFA :
2019-08-29 15:10:54 +02:00
case TIFF_PHOTOMETRIC_LINEAR_RAW : // Used by DNG images
2013-09-30 07:39:51 +03:00
s - > photometric = value ;
2006-11-13 13:20:50 +02:00
break ;
2013-09-30 07:39:51 +03:00
case TIFF_PHOTOMETRIC_ALPHA_MASK :
case TIFF_PHOTOMETRIC_CIE_LAB :
case TIFF_PHOTOMETRIC_ICC_LAB :
case TIFF_PHOTOMETRIC_ITU_LAB :
case TIFF_PHOTOMETRIC_LOG_L :
case TIFF_PHOTOMETRIC_LOG_LUV :
avpriv_report_missing_feature ( s - > avctx ,
" PhotometricInterpretation 0x%04X " ,
value ) ;
return AVERROR_PATCHWELCOME ;
2006-11-13 13:20:50 +02:00
default :
2013-09-30 07:39:51 +03:00
av_log ( s - > avctx , AV_LOG_ERROR , " PhotometricInterpretation %u is "
" unknown \n " , value ) ;
2012-11-17 15:40:37 +03:00
return AVERROR_INVALIDDATA ;
2006-11-13 07:32:10 +02:00
}
break ;
2009-09-24 21:30:28 +03:00
case TIFF_FILL_ORDER :
2012-04-13 04:28:37 +03:00
if ( value < 1 | | value > 2 ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
" Unknown FillOrder value %d, trying default one \n " , value ) ;
2009-09-24 21:30:28 +03:00
value = 1 ;
}
s - > fill_order = value - 1 ;
break ;
2013-09-30 02:47:55 +03:00
case TIFF_PAL : {
GetByteContext pal_gb [ 3 ] ;
2006-11-13 13:34:46 +02:00
off = type_sizes [ type ] ;
2013-09-30 02:47:55 +03:00
if ( count / 3 > 256 | |
bytestream2_get_bytes_left ( & s - > gb ) < count / 3 * off * 3 )
2012-11-17 15:40:37 +03:00
return AVERROR_INVALIDDATA ;
2014-04-13 04:01:03 +03:00
2013-09-30 02:47:55 +03:00
pal_gb [ 0 ] = pal_gb [ 1 ] = pal_gb [ 2 ] = s - > gb ;
bytestream2_skip ( & pal_gb [ 1 ] , count / 3 * off ) ;
bytestream2_skip ( & pal_gb [ 2 ] , count / 3 * off * 2 ) ;
2014-04-13 04:54:11 +03:00
2006-11-13 13:34:46 +02:00
off = ( type_sizes [ type ] - 1 ) < < 3 ;
2017-03-14 02:34:14 +02:00
if ( off > 31U ) {
av_log ( s - > avctx , AV_LOG_ERROR , " palette shift %d is out of range \n " , off ) ;
return AVERROR_INVALIDDATA ;
}
2012-04-13 04:28:37 +03:00
for ( i = 0 ; i < count / 3 ; i + + ) {
2013-09-28 19:20:19 +03:00
uint32_t p = 0xFF000000 ;
2014-04-13 04:54:11 +03:00
p | = ( ff_tget ( & pal_gb [ 0 ] , type , s - > le ) > > off ) < < 16 ;
p | = ( ff_tget ( & pal_gb [ 1 ] , type , s - > le ) > > off ) < < 8 ;
p | = ff_tget ( & pal_gb [ 2 ] , type , s - > le ) > > off ;
2013-09-30 08:00:20 +03:00
s - > palette [ i ] = p ;
2006-11-13 07:32:10 +02:00
}
2011-05-24 02:17:25 +03:00
s - > palette_is_set = 1 ;
2006-11-13 13:38:42 +02:00
break ;
2013-09-30 02:47:55 +03:00
}
2006-11-13 13:38:42 +02:00
case TIFF_PLANAR :
2013-05-09 22:39:32 +03:00
s - > planar = value = = 2 ;
2006-11-13 13:38:42 +02:00
break ;
2014-04-27 19:44:58 +03:00
case TIFF_YCBCR_SUBSAMPLING :
if ( count ! = 2 ) {
av_log ( s - > avctx , AV_LOG_ERROR , " subsample count invalid \n " ) ;
return AVERROR_INVALIDDATA ;
}
2016-01-18 04:31:25 +02:00
for ( i = 0 ; i < count ; i + + ) {
2014-04-27 19:44:58 +03:00
s - > subsampling [ i ] = ff_tget ( & s - > gb , type , s - > le ) ;
2016-01-18 04:31:25 +02:00
if ( s - > subsampling [ i ] < = 0 ) {
av_log ( s - > avctx , AV_LOG_ERROR , " subsampling %d is invalid \n " , s - > subsampling [ i ] ) ;
2017-05-15 21:19:06 +02:00
s - > subsampling [ i ] = 1 ;
2016-01-18 04:31:25 +02:00
return AVERROR_INVALIDDATA ;
}
}
2014-04-27 19:44:58 +03:00
break ;
2008-12-26 20:42:26 +02:00
case TIFF_T4OPTIONS :
2012-04-13 04:28:37 +03:00
if ( s - > compr = = TIFF_G3 )
2009-09-28 08:15:27 +03:00
s - > fax_opts = value ;
break ;
2008-12-26 20:42:26 +02:00
case TIFF_T6OPTIONS :
2012-04-13 04:28:37 +03:00
if ( s - > compr = = TIFF_G4 )
2009-09-28 08:15:27 +03:00
s - > fax_opts = value ;
2008-12-26 20:42:26 +02:00
break ;
2011-10-04 01:19:52 +03:00
# define ADD_METADATA(count, name, sep)\
2013-03-13 20:51:17 +03:00
if ( ( ret = add_metadata ( count , type , name , sep , s , frame ) ) < 0 ) { \
2011-10-04 01:19:52 +03:00
av_log ( s - > avctx , AV_LOG_ERROR , " Error allocating temporary buffer \n " ) ; \
2013-08-11 15:16:09 +03:00
goto end ; \
2011-10-04 01:19:52 +03:00
}
case TIFF_MODEL_PIXEL_SCALE :
ADD_METADATA ( count , " ModelPixelScaleTag " , NULL ) ;
break ;
case TIFF_MODEL_TRANSFORMATION :
ADD_METADATA ( count , " ModelTransformationTag " , NULL ) ;
break ;
case TIFF_MODEL_TIEPOINT :
ADD_METADATA ( count , " ModelTiepointTag " , NULL ) ;
break ;
case TIFF_GEO_KEY_DIRECTORY :
2017-03-13 21:45:08 +02:00
if ( s - > geotag_count ) {
avpriv_request_sample ( s - > avctx , " Multiple geo key directories \n " ) ;
return AVERROR_INVALIDDATA ;
}
2011-10-04 01:19:52 +03:00
ADD_METADATA ( 1 , " GeoTIFF_Version " , NULL ) ;
ADD_METADATA ( 2 , " GeoTIFF_Key_Revision " , " . " ) ;
2013-08-12 20:32:40 +03:00
s - > geotag_count = ff_tget_short ( & s - > gb , s - > le ) ;
2011-10-04 01:19:52 +03:00
if ( s - > geotag_count > count / 4 - 1 ) {
s - > geotag_count = count / 4 - 1 ;
av_log ( s - > avctx , AV_LOG_WARNING , " GeoTIFF key directory buffer shorter than specified \n " ) ;
}
2017-03-21 02:55:01 +02:00
if ( bytestream2_get_bytes_left ( & s - > gb ) < s - > geotag_count * sizeof ( int16_t ) * 4
| | s - > geotag_count = = 0 ) {
2013-02-10 22:24:22 +03:00
s - > geotag_count = 0 ;
2012-07-16 03:31:11 +03:00
return - 1 ;
2013-02-10 22:24:22 +03:00
}
2014-04-20 18:32:17 +03:00
s - > geotags = av_mallocz_array ( s - > geotag_count , sizeof ( TiffGeoTag ) ) ;
2011-10-04 01:19:52 +03:00
if ( ! s - > geotags ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Error allocating temporary buffer \n " ) ;
2013-02-10 22:24:22 +03:00
s - > geotag_count = 0 ;
2013-08-11 15:16:09 +03:00
goto end ;
2011-10-04 01:19:52 +03:00
}
for ( i = 0 ; i < s - > geotag_count ; i + + ) {
2013-08-12 20:32:40 +03:00
s - > geotags [ i ] . key = ff_tget_short ( & s - > gb , s - > le ) ;
s - > geotags [ i ] . type = ff_tget_short ( & s - > gb , s - > le ) ;
s - > geotags [ i ] . count = ff_tget_short ( & s - > gb , s - > le ) ;
2011-10-04 01:19:52 +03:00
if ( ! s - > geotags [ i ] . type )
2013-08-12 20:32:40 +03:00
s - > geotags [ i ] . val = get_geokey_val ( s - > geotags [ i ] . key , ff_tget_short ( & s - > gb , s - > le ) ) ;
2011-10-04 01:19:52 +03:00
else
2013-08-12 20:32:40 +03:00
s - > geotags [ i ] . offset = ff_tget_short ( & s - > gb , s - > le ) ;
2011-10-04 01:19:52 +03:00
}
break ;
case TIFF_GEO_DOUBLE_PARAMS :
2012-07-16 03:31:11 +03:00
if ( count > = INT_MAX / sizeof ( int64_t ) )
return AVERROR_INVALIDDATA ;
if ( bytestream2_get_bytes_left ( & s - > gb ) < count * sizeof ( int64_t ) )
return AVERROR_INVALIDDATA ;
2014-04-20 18:32:17 +03:00
dp = av_malloc_array ( count , sizeof ( double ) ) ;
2011-10-04 01:19:52 +03:00
if ( ! dp ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Error allocating temporary buffer \n " ) ;
2013-08-11 15:16:09 +03:00
goto end ;
2011-10-04 01:19:52 +03:00
}
for ( i = 0 ; i < count ; i + + )
2013-08-12 20:32:40 +03:00
dp [ i ] = ff_tget_double ( & s - > gb , s - > le ) ;
2011-10-04 01:19:52 +03:00
for ( i = 0 ; i < s - > geotag_count ; i + + ) {
if ( s - > geotags [ i ] . type = = TIFF_GEO_DOUBLE_PARAMS ) {
if ( s - > geotags [ i ] . count = = 0
| | s - > geotags [ i ] . offset + s - > geotags [ i ] . count > count ) {
av_log ( s - > avctx , AV_LOG_WARNING , " Invalid GeoTIFF key %d \n " , s - > geotags [ i ] . key ) ;
2017-06-11 01:05:26 +02:00
} else if ( s - > geotags [ i ] . val ) {
av_log ( s - > avctx , AV_LOG_WARNING , " Duplicate GeoTIFF key %d \n " , s - > geotags [ i ] . key ) ;
2011-10-04 01:19:52 +03:00
} else {
char * ap = doubles2str ( & dp [ s - > geotags [ i ] . offset ] , s - > geotags [ i ] . count , " , " ) ;
if ( ! ap ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Error allocating temporary buffer \n " ) ;
av_freep ( & dp ) ;
return AVERROR ( ENOMEM ) ;
}
s - > geotags [ i ] . val = ap ;
}
}
}
av_freep ( & dp ) ;
break ;
case TIFF_GEO_ASCII_PARAMS :
2012-07-15 23:58:13 +03:00
pos = bytestream2_tell ( & s - > gb ) ;
2011-10-04 01:19:52 +03:00
for ( i = 0 ; i < s - > geotag_count ; i + + ) {
if ( s - > geotags [ i ] . type = = TIFF_GEO_ASCII_PARAMS ) {
if ( s - > geotags [ i ] . count = = 0
| | s - > geotags [ i ] . offset + s - > geotags [ i ] . count > count ) {
av_log ( s - > avctx , AV_LOG_WARNING , " Invalid GeoTIFF key %d \n " , s - > geotags [ i ] . key ) ;
} else {
2012-07-16 03:31:11 +03:00
char * ap ;
bytestream2_seek ( & s - > gb , pos + s - > geotags [ i ] . offset , SEEK_SET ) ;
if ( bytestream2_get_bytes_left ( & s - > gb ) < s - > geotags [ i ] . count )
2013-01-07 03:24:32 +03:00
return AVERROR_INVALIDDATA ;
2017-06-05 20:39:21 +02:00
if ( s - > geotags [ i ] . val )
return AVERROR_INVALIDDATA ;
2012-07-16 03:31:11 +03:00
ap = av_malloc ( s - > geotags [ i ] . count ) ;
2011-10-04 01:19:52 +03:00
if ( ! ap ) {
av_log ( s - > avctx , AV_LOG_ERROR , " Error allocating temporary buffer \n " ) ;
return AVERROR ( ENOMEM ) ;
}
2012-07-16 03:31:11 +03:00
bytestream2_get_bufferu ( & s - > gb , ap , s - > geotags [ i ] . count ) ;
2011-10-04 01:19:52 +03:00
ap [ s - > geotags [ i ] . count - 1 ] = ' \0 ' ; //replace the "|" delimiter with a 0 byte
s - > geotags [ i ] . val = ap ;
}
}
}
break ;
2012-07-16 03:55:18 +03:00
case TIFF_ARTIST :
ADD_METADATA ( count , " artist " , NULL ) ;
break ;
case TIFF_COPYRIGHT :
ADD_METADATA ( count , " copyright " , NULL ) ;
break ;
case TIFF_DATE :
ADD_METADATA ( count , " date " , NULL ) ;
break ;
case TIFF_DOCUMENT_NAME :
ADD_METADATA ( count , " document_name " , NULL ) ;
break ;
case TIFF_HOST_COMPUTER :
ADD_METADATA ( count , " computer " , NULL ) ;
break ;
case TIFF_IMAGE_DESCRIPTION :
ADD_METADATA ( count , " description " , NULL ) ;
break ;
case TIFF_MAKE :
ADD_METADATA ( count , " make " , NULL ) ;
break ;
case TIFF_MODEL :
ADD_METADATA ( count , " model " , NULL ) ;
break ;
case TIFF_PAGE_NAME :
ADD_METADATA ( count , " page_name " , NULL ) ;
break ;
case TIFF_PAGE_NUMBER :
ADD_METADATA ( count , " page_number " , " / " ) ;
2019-03-22 17:55:56 +02:00
// 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 ) ;
2012-07-16 03:55:18 +03:00
break ;
case TIFF_SOFTWARE_NAME :
ADD_METADATA ( count , " software " , NULL ) ;
break ;
2019-05-30 12:42:42 +02:00
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 ;
2011-05-09 22:26:39 +03:00
default :
2013-06-03 05:00:43 +03:00
if ( s - > avctx - > err_recognition & AV_EF_EXPLODE ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
2018-10-30 23:05:52 +02:00
" Unknown or unsupported tag %d/0x%0X \n " ,
2013-06-03 05:00:43 +03:00
tag , tag ) ;
return AVERROR_INVALIDDATA ;
}
2006-10-13 13:48:29 +03:00
}
2013-08-11 15:16:09 +03:00
end :
2015-03-09 00:27:43 +02:00
if ( s - > bpp > 64U ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
" This format is not supported (bpp=%d, %d components) \n " ,
s - > bpp , count ) ;
s - > bpp = 0 ;
return AVERROR_INVALIDDATA ;
}
2012-07-15 23:58:13 +03:00
bytestream2_seek ( & s - > gb , start , SEEK_SET ) ;
2006-10-13 13:48:29 +03:00
return 0 ;
}
static int decode_frame ( AVCodecContext * avctx ,
2012-11-13 21:35:22 +03:00
void * data , int * got_frame , AVPacket * avpkt )
2006-10-13 13:48:29 +03:00
{
2012-04-13 04:28:37 +03:00
TiffContext * const s = avctx - > priv_data ;
2012-11-21 23:34:46 +03:00
AVFrame * const p = data ;
2013-08-09 17:01:46 +03:00
ThreadFrame frame = { . f = data } ;
2019-08-09 01:23:46 +02:00
unsigned off , last_off ;
2013-08-12 20:32:40 +03:00
int le , ret , plane , planes ;
2013-06-01 16:35:11 +03:00
int i , j , entries , stride ;
2011-10-01 01:45:03 +03:00
unsigned soff , ssize ;
2008-12-22 08:50:18 +02:00
uint8_t * dst ;
2012-07-15 23:58:13 +03:00
GetByteContext stripsizes ;
GetByteContext stripdata ;
2019-03-22 17:55:56 +02:00
int retry_for_subifd , retry_for_page ;
2019-08-29 15:10:53 +02:00
int is_dng ;
2012-07-15 23:58:13 +03:00
bytestream2_init ( & s - > gb , avpkt - > data , avpkt - > size ) ;
2006-10-13 13:48:29 +03:00
2013-06-01 16:35:11 +03:00
// parse image header
2013-08-12 20:32:40 +03:00
if ( ( ret = ff_tdecode_header ( & s - > gb , & le , & off ) ) ) {
av_log ( avctx , AV_LOG_ERROR , " Invalid TIFF header \n " ) ;
return ret ;
} else if ( off > = UINT_MAX - 14 | | avpkt - > size < off + 14 ) {
av_log ( avctx , AV_LOG_ERROR , " IFD offset is greater than image size \n " ) ;
2012-11-17 15:40:37 +03:00
return AVERROR_INVALIDDATA ;
2006-10-13 13:48:29 +03:00
}
2013-09-30 07:39:51 +03:00
s - > le = le ;
2012-09-12 14:33:57 +03:00
// TIFF_BPP is not a required tag and defaults to 1
2019-08-29 15:10:41 +02:00
s - > tiff_type = TIFF_TYPE_TIFF ;
2018-10-30 23:05:52 +02:00
again :
2019-05-30 12:42:40 +02:00
s - > is_thumbnail = 0 ;
2014-04-13 04:45:45 +03:00
s - > bppcount = s - > bpp = 1 ;
2013-09-30 07:39:51 +03:00
s - > photometric = TIFF_PHOTOMETRIC_NONE ;
s - > compr = TIFF_RAW ;
s - > fill_order = 0 ;
2018-10-30 23:05:52 +02:00
s - > white_level = 0 ;
s - > is_bayer = 0 ;
2019-08-29 15:10:41 +02:00
s - > is_tiled = 0 ;
s - > is_jpeg = 0 ;
2019-03-22 17:55:56 +02:00
s - > cur_page = 0 ;
2019-08-31 21:14:28 +02:00
for ( i = 0 ; i < 65536 ; i + + )
s - > dng_lut [ i ] = i ;
2011-10-04 01:19:52 +03:00
free_geotags ( s ) ;
2012-07-15 23:58:13 +03:00
// Reset these offsets so we can tell if they were set this frame
s - > stripsizesoff = s - > strippos = 0 ;
2006-10-13 13:48:29 +03:00
/* parse image file directory */
2012-07-15 23:58:13 +03:00
bytestream2_seek ( & s - > gb , off , SEEK_SET ) ;
2013-08-12 20:32:40 +03:00
entries = ff_tget_short ( & s - > gb , le ) ;
2012-07-16 03:31:11 +03:00
if ( bytestream2_get_bytes_left ( & s - > gb ) < entries * 12 )
return AVERROR_INVALIDDATA ;
2012-04-13 04:28:37 +03:00
for ( i = 0 ; i < entries ; i + + ) {
2013-03-13 20:51:17 +03:00
if ( ( ret = tiff_decode_tag ( s , p ) ) < 0 )
2013-01-07 03:24:32 +03:00
return ret ;
2006-10-13 13:48:29 +03:00
}
2011-10-04 01:19:52 +03:00
2019-05-30 12:42:40 +02:00
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 */
2019-03-22 17:55:56 +02:00
retry_for_page = s - > get_page & & s - > cur_page + 1 < s - > get_page ; // get_page is 1-indexed
2019-08-09 01:23:46 +02:00
last_off = off ;
2019-03-22 17:55:56 +02:00
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
2018-10-30 23:05:52 +02:00
off = s - > sub_ifd ;
2019-03-22 17:55:56 +02:00
}
if ( retry_for_subifd | | retry_for_page ) {
2019-08-09 01:23:46 +02:00
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 \n " ) ;
return AVERROR_INVALIDDATA ;
}
2018-10-30 23:05:52 +02:00
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 ;
}
s - > sub_ifd = 0 ;
goto again ;
}
2019-08-29 15:10:53 +02:00
/* 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 ) ;
2011-10-04 01:19:52 +03:00
for ( i = 0 ; i < s - > geotag_count ; i + + ) {
const char * keyname = get_geokey_name ( s - > geotags [ i ] . key ) ;
if ( ! keyname ) {
av_log ( avctx , AV_LOG_WARNING , " Unknown or unsupported GeoTIFF key %d \n " , s - > geotags [ i ] . key ) ;
continue ;
}
if ( get_geokey_type ( s - > geotags [ i ] . key ) ! = s - > geotags [ i ] . type ) {
av_log ( avctx , AV_LOG_WARNING , " Type of GeoTIFF key %d is wrong \n " , s - > geotags [ i ] . key ) ;
continue ;
}
2017-04-22 10:54:58 +02:00
ret = av_dict_set ( & p - > metadata , keyname , s - > geotags [ i ] . val , 0 ) ;
2011-10-04 01:19:52 +03:00
if ( ret < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " Writing metadata with key '%s' failed \n " , keyname ) ;
return ret ;
}
}
2019-08-29 15:10:53 +02:00
if ( is_dng ) {
if ( s - > white_level = = 0 )
s - > white_level = ( 1 < < s - > bpp ) - 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 ;
}
}
2019-08-29 15:10:46 +02:00
if ( ! s - > is_tiled & & ! s - > strippos & & ! s - > stripoff ) {
2008-12-22 08:50:18 +02:00
av_log ( avctx , AV_LOG_ERROR , " Image data is missing \n " ) ;
2012-11-17 15:40:37 +03:00
return AVERROR_INVALIDDATA ;
2008-12-22 08:50:18 +02:00
}
2019-08-29 15:10:53 +02:00
2008-12-22 08:50:18 +02:00
/* now we have the data and may start decoding */
2013-08-09 17:01:46 +03:00
if ( ( ret = init_image ( s , & frame ) ) < 0 )
2011-05-09 13:51:24 +03:00
return ret ;
2019-08-29 15:10:46 +02:00
if ( ! s - > is_tiled ) {
if ( s - > strips = = 1 & & ! s - > stripsize ) {
av_log ( avctx , AV_LOG_WARNING , " Image data size missing \n " ) ;
s - > stripsize = avpkt - > size - s - > stripoff ;
}
2012-07-15 23:58:13 +03:00
2019-08-29 15:10:46 +02:00
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 ) ;
}
2012-07-15 23:58:13 +03:00
2019-08-29 15:10:46 +02:00
if ( s - > rps < = 0 | | s - > rps % s - > subsampling [ 1 ] ) {
av_log ( avctx , AV_LOG_ERROR , " rps %d invalid \n " , s - > rps ) ;
return AVERROR_INVALIDDATA ;
}
2012-11-09 21:28:23 +03:00
}
2019-08-31 20:57:29 +02:00
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 ;
}
2019-08-29 15:10:41 +02:00
/* Handle DNG images with JPEG-compressed tiles */
2019-08-29 15:10:53 +02:00
if ( is_dng & & s - > is_tiled ) {
2019-08-29 15:10:41 +02:00
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 {
2019-08-29 15:10:52 +02:00
if ( ( ret = dng_decode_tiles ( avctx , ( AVFrame * ) data , avpkt ) ) > 0 )
2019-08-29 15:10:41 +02:00
* got_frame = 1 ;
return ret ;
}
}
/* Handle TIFF images and DNG images with uncompressed strips (non-tiled) */
2013-05-09 22:39:32 +03:00
planes = s - > planar ? s - > bppcount : 1 ;
for ( plane = 0 ; plane < planes ; plane + + ) {
2019-03-20 18:50:25 +02:00
uint8_t * five_planes = NULL ;
2018-10-02 03:04:50 +02:00
int remaining = avpkt - > size ;
2018-11-23 03:33:04 +02:00
int decoded_height ;
2013-05-09 22:39:32 +03:00
stride = p - > linesize [ plane ] ;
2014-12-17 15:54:44 +02:00
dst = p - > data [ plane ] ;
2019-03-20 18:50:25 +02:00
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 ) ;
}
2014-12-17 15:54:44 +02:00
for ( i = 0 ; i < s - > height ; i + = s - > rps ) {
2017-06-22 20:21:05 +02:00
if ( i )
dst + = s - > rps * stride ;
2014-12-17 15:54:44 +02:00
if ( s - > stripsizesoff )
2015-01-15 07:00:25 +02:00
ssize = ff_tget ( & stripsizes , s - > sstype , le ) ;
2014-12-17 15:54:44 +02:00
else
ssize = s - > stripsize ;
if ( s - > strippos )
2015-01-15 07:00:25 +02:00
soff = ff_tget ( & stripdata , s - > sot , le ) ;
2014-12-17 15:54:44 +02:00
else
soff = s - > stripoff ;
2018-10-02 03:04:50 +02:00
if ( soff > avpkt - > size | | ssize > avpkt - > size - soff | | ssize > remaining ) {
2014-12-17 15:54:44 +02:00
av_log ( avctx , AV_LOG_ERROR , " Invalid strip size/offset \n " ) ;
2019-03-20 18:50:25 +02:00
av_freep ( & five_planes ) ;
2014-12-17 15:54:44 +02:00
return AVERROR_INVALIDDATA ;
2011-09-25 17:00:04 +03:00
}
2018-10-02 03:04:50 +02:00
remaining - = ssize ;
2015-01-15 07:00:25 +02:00
if ( ( ret = tiff_unpack_strip ( s , p , dst , stride , avpkt - > data + soff , ssize , i ,
2014-12-17 15:54:44 +02:00
FFMIN ( s - > rps , s - > height - i ) ) ) < 0 ) {
2019-03-20 18:50:25 +02:00
if ( avctx - > err_recognition & AV_EF_EXPLODE ) {
av_freep ( & five_planes ) ;
2014-12-17 15:54:44 +02:00
return ret ;
2019-03-20 18:50:25 +02:00
}
2014-12-17 15:54:44 +02:00
break ;
2011-09-25 17:00:04 +03:00
}
2014-04-27 20:52:37 +03:00
}
2018-11-23 03:33:04 +02:00
decoded_height = FFMIN ( i , s - > height ) ;
2014-12-17 15:54:44 +02:00
if ( s - > predictor = = 2 ) {
2015-01-15 07:00:25 +02:00
if ( s - > photometric = = TIFF_PHOTOMETRIC_YCBCR ) {
av_log ( s - > avctx , AV_LOG_ERROR , " predictor == 2 with YUV is unsupported " ) ;
return AVERROR_PATCHWELCOME ;
2011-09-25 17:00:04 +03:00
}
2019-03-20 18:50:25 +02:00
dst = five_planes ? five_planes : p - > data [ plane ] ;
2014-12-17 15:54:44 +02:00
soff = s - > bpp > > 3 ;
2015-01-15 07:00:25 +02:00
if ( s - > planar )
soff = FFMAX ( soff / s - > bppcount , 1 ) ;
2014-12-17 15:54:44 +02:00
ssize = s - > width * soff ;
if ( s - > avctx - > pix_fmt = = AV_PIX_FMT_RGB48LE | |
2015-01-15 07:00:25 +02:00
s - > avctx - > pix_fmt = = AV_PIX_FMT_RGBA64LE | |
2015-01-30 15:12:55 +02:00
s - > avctx - > pix_fmt = = AV_PIX_FMT_GRAY16LE | |
s - > avctx - > pix_fmt = = AV_PIX_FMT_YA16LE | |
2015-01-15 07:00:25 +02:00
s - > avctx - > pix_fmt = = AV_PIX_FMT_GBRP16LE | |
s - > avctx - > pix_fmt = = AV_PIX_FMT_GBRAP16LE ) {
2018-11-23 03:33:04 +02:00
for ( i = 0 ; i < decoded_height ; i + + ) {
2014-12-17 15:54:44 +02:00
for ( j = soff ; j < ssize ; j + = 2 )
AV_WL16 ( dst + j , AV_RL16 ( dst + j ) + AV_RL16 ( dst + j - soff ) ) ;
dst + = stride ;
}
} else if ( s - > avctx - > pix_fmt = = AV_PIX_FMT_RGB48BE | |
2015-01-15 07:00:25 +02:00
s - > avctx - > pix_fmt = = AV_PIX_FMT_RGBA64BE | |
2015-01-30 15:12:55 +02:00
s - > avctx - > pix_fmt = = AV_PIX_FMT_GRAY16BE | |
s - > avctx - > pix_fmt = = AV_PIX_FMT_YA16BE | |
2015-01-15 07:00:25 +02:00
s - > avctx - > pix_fmt = = AV_PIX_FMT_GBRP16BE | |
s - > avctx - > pix_fmt = = AV_PIX_FMT_GBRAP16BE ) {
2018-11-23 03:33:04 +02:00
for ( i = 0 ; i < decoded_height ; i + + ) {
2014-12-17 15:54:44 +02:00
for ( j = soff ; j < ssize ; j + = 2 )
AV_WB16 ( dst + j , AV_RB16 ( dst + j ) + AV_RB16 ( dst + j - soff ) ) ;
dst + = stride ;
}
} else {
2018-11-23 03:33:04 +02:00
for ( i = 0 ; i < decoded_height ; i + + ) {
2014-12-17 15:54:44 +02:00
for ( j = soff ; j < ssize ; j + + )
dst [ j ] + = dst [ j - soff ] ;
dst + = stride ;
}
2011-09-25 17:00:04 +03:00
}
2014-12-17 15:54:44 +02:00
}
if ( s - > photometric = = TIFF_PHOTOMETRIC_WHITE_IS_ZERO ) {
2017-04-11 03:37:35 +02:00
int c = ( s - > avctx - > pix_fmt = = AV_PIX_FMT_PAL8 ? ( 1 < < s - > bpp ) - 1 : 255 ) ;
2014-12-17 15:54:44 +02:00
dst = p - > data [ plane ] ;
2012-04-14 22:49:01 +03:00
for ( i = 0 ; i < s - > height ; i + + ) {
2014-12-17 15:54:44 +02:00
for ( j = 0 ; j < stride ; j + + )
2017-04-11 03:37:35 +02:00
dst [ j ] = c - dst [ j ] ;
2011-09-23 09:22:31 +03:00
dst + = stride ;
}
2011-09-25 17:00:04 +03:00
}
2019-01-12 18:27:48 +02:00
if ( s - > photometric = = TIFF_PHOTOMETRIC_SEPARATED & &
2019-03-20 18:50:25 +02:00
( 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 ] ;
2019-01-12 18:27:48 +02:00
dst = p - > data [ plane ] ;
for ( i = 0 ; i < s - > height ; i + + ) {
for ( j = 0 ; j < s - > width ; j + + ) {
2019-03-20 18:50:25 +02:00
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 ;
2019-01-12 18:27:48 +02:00
dst [ 4 * j ] = r * 257 > > 16 ;
dst [ 4 * j + 1 ] = g * 257 > > 16 ;
dst [ 4 * j + 2 ] = b * 257 > > 16 ;
2019-03-20 18:50:25 +02:00
dst [ 4 * j + 3 ] = s - > avctx - > pix_fmt = = AV_PIX_FMT_RGBA ? src [ x * j + 4 ] : 255 ;
2019-01-12 18:27:48 +02:00
}
2019-03-20 18:50:25 +02:00
src + = stride ;
2019-01-12 18:27:48 +02:00
dst + = p - > linesize [ plane ] ;
}
2019-03-20 18:50:25 +02:00
av_freep ( & five_planes ) ;
2019-03-09 12:05:36 +02:00
} 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 ] ;
}
2019-01-12 18:27:48 +02:00
}
2008-12-22 08:50:18 +02:00
}
2006-10-13 13:48:29 +03:00
2013-06-02 17:50:39 +03:00
if ( s - > planar & & s - > bppcount > 2 ) {
2013-05-09 22:39:32 +03:00
FFSWAP ( uint8_t * , p - > data [ 0 ] , p - > data [ 2 ] ) ;
FFSWAP ( int , p - > linesize [ 0 ] , p - > linesize [ 2 ] ) ;
FFSWAP ( uint8_t * , p - > data [ 0 ] , p - > data [ 1 ] ) ;
FFSWAP ( int , p - > linesize [ 0 ] , p - > linesize [ 1 ] ) ;
}
2019-08-29 15:10:53 +02:00
if ( s - > is_bayer & & s - > white_level & & s - > bpp = = 16 & & ! is_dng ) {
2018-10-30 23:05:52 +02:00
uint16_t * dst = ( uint16_t * ) p - > data [ 0 ] ;
for ( i = 0 ; i < s - > height ; i + + ) {
for ( j = 0 ; j < s - > width ; j + + )
dst [ j ] = FFMIN ( ( dst [ j ] / ( float ) s - > white_level ) * 65535 , 65535 ) ;
dst + = stride / 2 ;
}
}
2012-11-13 21:35:22 +03:00
* got_frame = 1 ;
2006-10-13 13:48:29 +03:00
2012-07-15 23:58:13 +03:00
return avpkt - > size ;
2006-10-13 13:48:29 +03:00
}
2012-04-13 04:28:37 +03:00
static av_cold int tiff_init ( AVCodecContext * avctx )
{
2006-10-13 13:48:29 +03:00
TiffContext * s = avctx - > priv_data ;
2019-08-29 15:10:41 +02:00
const AVCodec * codec ;
int ret ;
2006-10-13 13:48:29 +03:00
2013-06-01 16:35:11 +03:00
s - > width = 0 ;
2006-10-13 13:48:29 +03:00
s - > height = 0 ;
2014-04-27 19:44:58 +03:00
s - > subsampling [ 0 ] =
2019-09-26 00:34:44 +02:00
s - > subsampling [ 1 ] = 1 ;
2013-06-01 16:35:11 +03:00
s - > avctx = avctx ;
2006-10-26 07:15:48 +03:00
ff_lzw_decode_open ( & s - > lzw ) ;
2018-09-09 11:38:33 +02:00
if ( ! s - > lzw )
return AVERROR ( ENOMEM ) ;
2008-12-26 20:42:26 +02:00
ff_ccitt_unpack_init ( ) ;
2006-10-13 13:48:29 +03:00
2019-08-29 15:10:41 +02:00
/* Allocate JPEG frame */
s - > jpgframe = av_frame_alloc ( ) ;
if ( ! s - > jpgframe )
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 = ff_codec_open2_recursive ( s - > avctx_mjpeg , codec , NULL ) ;
if ( ret < 0 ) {
return ret ;
}
2006-10-13 13:48:29 +03:00
return 0 ;
}
2008-03-21 05:11:20 +02:00
static av_cold int tiff_end ( AVCodecContext * avctx )
2006-10-13 13:48:29 +03:00
{
2012-04-13 04:28:37 +03:00
TiffContext * const s = avctx - > priv_data ;
2006-10-13 13:48:29 +03:00
2011-10-04 01:19:52 +03:00
free_geotags ( s ) ;
2006-10-26 07:15:48 +03:00
ff_lzw_decode_close ( & s - > lzw ) ;
2012-12-20 18:36:44 +03:00
av_freep ( & s - > deinvert_buf ) ;
2017-06-04 00:25:09 +02:00
s - > deinvert_buf_size = 0 ;
2018-12-11 01:52:16 +02:00
av_freep ( & s - > yuv_line ) ;
s - > yuv_line_size = 0 ;
2017-06-03 23:57:58 +02:00
av_freep ( & s - > fax_buffer ) ;
s - > fax_buffer_size = 0 ;
2019-08-29 15:10:41 +02:00
av_frame_free ( & s - > jpgframe ) ;
avcodec_free_context ( & s - > avctx_mjpeg ) ;
2006-10-13 13:48:29 +03:00
return 0 ;
}
2018-10-30 23:05:52 +02:00
# 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 } ,
2019-05-30 12:42:40 +02:00
{ " 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 } ,
2019-03-22 17:55:56 +02:00
{ " 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 } ,
2018-10-30 23:05:52 +02:00
{ NULL } ,
} ;
static const AVClass tiff_decoder_class = {
. class_name = " TIFF decoder " ,
. item_name = av_default_item_name ,
. option = tiff_options ,
. version = LIBAVUTIL_VERSION_INT ,
} ;
2011-01-25 23:40:11 +02:00
AVCodec ff_tiff_decoder = {
2011-07-17 13:54:31 +03:00
. name = " tiff " ,
2013-06-01 16:35:11 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " TIFF image " ) ,
2011-07-17 13:54:31 +03:00
. type = AVMEDIA_TYPE_VIDEO ,
2012-08-05 12:11:04 +03:00
. id = AV_CODEC_ID_TIFF ,
2011-07-17 13:54:31 +03:00
. priv_data_size = sizeof ( TiffContext ) ,
. init = tiff_init ,
. close = tiff_end ,
. decode = decode_frame ,
2013-08-09 17:01:46 +03:00
. init_thread_copy = ONLY_IF_THREADS_ENABLED ( tiff_init ) ,
2015-07-27 22:21:19 +02:00
. capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS ,
2019-10-02 21:14:17 +02:00
. caps_internal = FF_CODEC_CAP_INIT_CLEANUP ,
2018-10-30 23:05:52 +02:00
. priv_class = & tiff_decoder_class ,
2006-10-13 13:48:29 +03:00
} ;