From 197078e331ba874e44f8f9938d96c3cbc44b0a2f Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Thu, 5 Oct 2017 19:54:13 +0300 Subject: [PATCH 1/8] 3rdparty: update zlib 1.2.11 --- 3rdparty/zlib/CMakeLists.txt | 32 +- 3rdparty/zlib/ChangeLog | 55 +- 3rdparty/zlib/README | 6 +- 3rdparty/zlib/adler32.c | 21 +- 3rdparty/zlib/compress.c | 42 +- 3rdparty/zlib/crc32.c | 41 +- 3rdparty/zlib/deflate.c | 860 +++++++++++++-------- 3rdparty/zlib/deflate.h | 35 +- 3rdparty/zlib/gzguts.h | 23 +- 3rdparty/zlib/gzlib.c | 31 +- 3rdparty/zlib/gzread.c | 158 ++-- 3rdparty/zlib/gzwrite.c | 334 +++++--- 3rdparty/zlib/infback.c | 4 +- 3rdparty/zlib/inffast.c | 85 +- 3rdparty/zlib/inflate.c | 123 ++- 3rdparty/zlib/inflate.h | 11 +- 3rdparty/zlib/inftrees.c | 26 +- 3rdparty/zlib/trees.c | 99 +-- 3rdparty/zlib/uncompr.c | 114 ++- 3rdparty/zlib/{zconf.h.cmakein => zconf.h} | 45 +- 3rdparty/zlib/zlib.h | 444 +++++++---- 3rdparty/zlib/zutil.c | 49 +- 3rdparty/zlib/zutil.h | 52 +- 23 files changed, 1673 insertions(+), 1017 deletions(-) rename 3rdparty/zlib/{zconf.h.cmakein => zconf.h} (93%) diff --git a/3rdparty/zlib/CMakeLists.txt b/3rdparty/zlib/CMakeLists.txt index 84d46189a6..cd1da16987 100644 --- a/3rdparty/zlib/CMakeLists.txt +++ b/3rdparty/zlib/CMakeLists.txt @@ -23,6 +23,9 @@ endif() # if(NOT MSVC) check_include_file(unistd.h Z_HAVE_UNISTD_H) + if(Z_HAVE_UNISTD_H) + add_definitions(-DZ_HAVE_UNISTD_H) + endif() endif() if(MSVC) @@ -38,12 +41,10 @@ if(HAVE_OFF64_T) add_definitions(-D_LARGEFILE64_SOURCE=1) endif() -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein" - "${CMAKE_CURRENT_BINARY_DIR}/zconf.h" @ONLY) -ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") +ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}") set(ZLIB_PUBLIC_HDRS - "${CMAKE_CURRENT_BINARY_DIR}/zconf.h" + zconf.h zlib.h ) set(ZLIB_PRIVATE_HDRS @@ -78,21 +79,18 @@ set(ZLIB_SRCS add_library(${ZLIB_LIBRARY} STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) set_target_properties(${ZLIB_LIBRARY} PROPERTIES DEFINE_SYMBOL ZLIB_DLL) -if(UNIX) - if(CMAKE_COMPILER_IS_GNUCXX OR CV_ICC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - endif() -endif() - -ocv_warnings_disable(CMAKE_C_FLAGS -Wshorten-64-to-32 -Wattributes -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshift-negative-value) +ocv_warnings_disable(CMAKE_C_FLAGS -Wshorten-64-to-32 -Wattributes -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshift-negative-value + -Wundef # _LFS64_LARGEFILE is not defined + /wd4267 # MSVS 2015 (x64) + zlib 1.2.11 +) set_target_properties(${ZLIB_LIBRARY} PROPERTIES - OUTPUT_NAME ${ZLIB_LIBRARY} - DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" - COMPILE_PDB_NAME ${ZLIB_LIBRARY} - COMPILE_PDB_NAME_DEBUG "${ZLIB_LIBRARY}${OPENCV_DEBUG_POSTFIX}" - ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH} - ) + OUTPUT_NAME ${ZLIB_LIBRARY} + DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" + COMPILE_PDB_NAME ${ZLIB_LIBRARY} + COMPILE_PDB_NAME_DEBUG "${ZLIB_LIBRARY}${OPENCV_DEBUG_POSTFIX}" + ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH} +) if(ENABLE_SOLUTION_FOLDERS) set_target_properties(${ZLIB_LIBRARY} PROPERTIES FOLDER "3rdparty") diff --git a/3rdparty/zlib/ChangeLog b/3rdparty/zlib/ChangeLog index f22aabaef5..30199a65a0 100644 --- a/3rdparty/zlib/ChangeLog +++ b/3rdparty/zlib/ChangeLog @@ -1,10 +1,53 @@ ChangeLog file for zlib +Changes in 1.2.11 (15 Jan 2017) +- Fix deflate stored bug when pulling last block from window +- Permit immediate deflateParams changes before any deflate input + +Changes in 1.2.10 (2 Jan 2017) +- Avoid warnings on snprintf() return value +- Fix bug in deflate_stored() for zero-length input +- Fix bug in gzwrite.c that produced corrupt gzip files +- Remove files to be installed before copying them in Makefile.in +- Add warnings when compiling with assembler code + +Changes in 1.2.9 (31 Dec 2016) +- Fix contrib/minizip to permit unzipping with desktop API [Zouzou] +- Improve contrib/blast to return unused bytes +- Assure that gzoffset() is correct when appending +- Improve compress() and uncompress() to support large lengths +- Fix bug in test/example.c where error code not saved +- Remedy Coverity warning [Randers-Pehrson] +- Improve speed of gzprintf() in transparent mode +- Fix inflateInit2() bug when windowBits is 16 or 32 +- Change DEBUG macro to ZLIB_DEBUG +- Avoid uninitialized access by gzclose_w() +- Allow building zlib outside of the source directory +- Fix bug that accepted invalid zlib header when windowBits is zero +- Fix gzseek() problem on MinGW due to buggy _lseeki64 there +- Loop on write() calls in gzwrite.c in case of non-blocking I/O +- Add --warn (-w) option to ./configure for more compiler warnings +- Reject a window size of 256 bytes if not using the zlib wrapper +- Fix bug when level 0 used with Z_HUFFMAN or Z_RLE +- Add --debug (-d) option to ./configure to define ZLIB_DEBUG +- Fix bugs in creating a very large gzip header +- Add uncompress2() function, which returns the input size used +- Assure that deflateParams() will not switch functions mid-block +- Dramatically speed up deflation for level 0 (storing) +- Add gzfread(), duplicating the interface of fread() +- Add gzfwrite(), duplicating the interface of fwrite() +- Add deflateGetDictionary() function +- Use snprintf() for later versions of Microsoft C +- Fix *Init macros to use z_ prefix when requested +- Replace as400 with os400 for OS/400 support [Monnerat] +- Add crc32_z() and adler32_z() functions with size_t lengths +- Update Visual Studio project files [AraHaan] + Changes in 1.2.8 (28 Apr 2013) - Update contrib/minizip/iowin32.c for Windows RT [Vollant] - Do not force Z_CONST for C++ -- Clean up contrib/vstudio [Ro§] +- Clean up contrib/vstudio [Roß] - Correct spelling error in zlib.h - Fix mixed line endings in contrib/vstudio @@ -34,7 +77,7 @@ Changes in 1.2.7.1 (24 Mar 2013) - Clean up the usage of z_const and respect const usage within zlib - Clean up examples/gzlog.[ch] comparisons of different types - Avoid shift equal to bits in type (caused endless loop) -- Fix unintialized value bug in gzputc() introduced by const patches +- Fix uninitialized value bug in gzputc() introduced by const patches - Fix memory allocation error in examples/zran.c [Nor] - Fix bug where gzopen(), gzclose() would write an empty file - Fix bug in gzclose() when gzwrite() runs out of memory @@ -194,7 +237,7 @@ Changes in 1.2.5.2 (17 Dec 2011) - Add a transparent write mode to gzopen() when 'T' is in the mode - Update python link in zlib man page - Get inffixed.h and MAKEFIXED result to match -- Add a ./config --solo option to make zlib subset with no libary use +- Add a ./config --solo option to make zlib subset with no library use - Add undocumented inflateResetKeep() function for CAB file decoding - Add --cover option to ./configure for gcc coverage testing - Add #define ZLIB_CONST option to use const in the z_stream interface @@ -564,7 +607,7 @@ Changes in 1.2.3.1 (16 August 2006) - Update make_vms.com [Zinser] - Use -fPIC for shared build in configure [Teredesai, Nicholson] - Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen] -- Use fdopen() (not _fdopen()) for Interix in zutil.h [BŠck] +- Use fdopen() (not _fdopen()) for Interix in zutil.h [Bäck] - Add some FAQ entries about the contrib directory - Update the MVS question in the FAQ - Avoid extraneous reads after EOF in gzio.c [Brown] @@ -1178,7 +1221,7 @@ Changes in 1.0.6 (19 Jan 1998) 386 asm code replacing longest_match(). contrib/iostream/ by Kevin Ruland A C++ I/O streams interface to the zlib gz* functions - contrib/iostream2/ by Tyge Løvset + contrib/iostream2/ by Tyge Løvset Another C++ I/O streams interface contrib/untgz/ by "Pedro A. Aranda Guti\irrez" A very simple tar.gz file extractor using zlib @@ -1267,7 +1310,7 @@ Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] - fix array overlay in deflate.c which sometimes caused bad compressed data - fix inflate bug with empty stored block - fix MSDOS medium model which was broken in 0.99 -- fix deflateParams() which could generated bad compressed data. +- fix deflateParams() which could generate bad compressed data. - Bytef is define'd instead of typedef'ed (work around Borland bug) - added an INDEX file - new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), diff --git a/3rdparty/zlib/README b/3rdparty/zlib/README index 5ca9d127ed..51106de475 100644 --- a/3rdparty/zlib/README +++ b/3rdparty/zlib/README @@ -1,6 +1,6 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.8 is a general purpose data compression library. All the code is +zlib 1.2.11 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and @@ -31,7 +31,7 @@ Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at http://marknelson.us/1997/01/01/zlib-engine/ . -The changes made in version 1.2.8 are documented in the file ChangeLog. +The changes made in version 1.2.11 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . @@ -84,7 +84,7 @@ Acknowledgments: Copyright notice: - (C) 1995-2013 Jean-loup Gailly and Mark Adler + (C) 1995-2017 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/3rdparty/zlib/adler32.c b/3rdparty/zlib/adler32.c index a868f073d8..d0be4380a3 100644 --- a/3rdparty/zlib/adler32.c +++ b/3rdparty/zlib/adler32.c @@ -1,5 +1,5 @@ /* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 1995-2011, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -7,11 +7,9 @@ #include "zutil.h" -#define local static - local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); -#define BASE 65521 /* largest prime smaller than 65536 */ +#define BASE 65521U /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ @@ -62,10 +60,10 @@ local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); #endif /* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) +uLong ZEXPORT adler32_z(adler, buf, len) uLong adler; const Bytef *buf; - uInt len; + z_size_t len; { unsigned long sum2; unsigned n; @@ -132,6 +130,15 @@ uLong ZEXPORT adler32(adler, buf, len) return adler | (sum2 << 16); } +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + return adler32_z(adler, buf, len); +} + /* ========================================================================= */ local uLong adler32_combine_(adler1, adler2, len2) uLong adler1; @@ -156,7 +163,7 @@ local uLong adler32_combine_(adler1, adler2, len2) sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; if (sum1 >= BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE; - if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); if (sum2 >= BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } diff --git a/3rdparty/zlib/compress.c b/3rdparty/zlib/compress.c index 6e9762676a..e2db404abf 100644 --- a/3rdparty/zlib/compress.c +++ b/3rdparty/zlib/compress.c @@ -1,5 +1,5 @@ /* compress.c -- compress a memory buffer - * Copyright (C) 1995-2005 Jean-loup Gailly. + * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -28,16 +28,11 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) { z_stream stream; int err; + const uInt max = (uInt)-1; + uLong left; - stream.next_in = (z_const Bytef *)source; - stream.avail_in = (uInt)sourceLen; -#ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; -#endif - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + left = *destLen; + *destLen = 0; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; @@ -46,15 +41,26 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) err = deflateInit(&stream, level); if (err != Z_OK) return err; - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; + stream.next_out = dest; + stream.avail_out = 0; + stream.next_in = (z_const Bytef *)source; + stream.avail_in = 0; - err = deflateEnd(&stream); - return err; + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (uLong)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen; + sourceLen -= stream.avail_in; + } + err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); + } while (err == Z_OK); + + *destLen = stream.total_out; + deflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : err; } /* =========================================================================== diff --git a/3rdparty/zlib/crc32.c b/3rdparty/zlib/crc32.c index 979a7190a3..9580440c0e 100644 --- a/3rdparty/zlib/crc32.c +++ b/3rdparty/zlib/crc32.c @@ -1,5 +1,5 @@ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster @@ -30,17 +30,15 @@ #include "zutil.h" /* for STDC and FAR definitions */ -#define local static - /* Definitions for doing the crc four data bytes at a time. */ #if !defined(NOBYFOUR) && defined(Z_U4) # define BYFOUR #endif #ifdef BYFOUR local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, unsigned)); + const unsigned char FAR *, z_size_t)); local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, unsigned)); + const unsigned char FAR *, z_size_t)); # define TBLS 8 #else # define TBLS 1 @@ -201,10 +199,10 @@ const z_crc_t FAR * ZEXPORT get_crc_table() #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 /* ========================================================================= */ -unsigned long ZEXPORT crc32(crc, buf, len) +unsigned long ZEXPORT crc32_z(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - uInt len; + z_size_t len; { if (buf == Z_NULL) return 0UL; @@ -235,8 +233,29 @@ unsigned long ZEXPORT crc32(crc, buf, len) return crc ^ 0xffffffffUL; } +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + return crc32_z(crc, buf, len); +} + #ifdef BYFOUR +/* + This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit + integer pointer type. This violates the strict aliasing rule, where a + compiler can assume, for optimization purposes, that two pointers to + fundamentally different types won't ever point to the same memory. This can + manifest as a problem only if one of the pointers is written to. This code + only reads from those pointers. So long as this code remains isolated in + this compilation unit, there won't be a problem. For this reason, this code + should not be copied and pasted into a compilation unit in which other code + writes to the buffer that is passed to these routines. + */ + /* ========================================================================= */ #define DOLIT4 c ^= *buf4++; \ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ @@ -247,7 +266,7 @@ unsigned long ZEXPORT crc32(crc, buf, len) local unsigned long crc32_little(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - unsigned len; + z_size_t len; { register z_crc_t c; register const z_crc_t FAR *buf4; @@ -278,7 +297,7 @@ local unsigned long crc32_little(crc, buf, len) } /* ========================================================================= */ -#define DOBIG4 c ^= *++buf4; \ +#define DOBIG4 c ^= *buf4++; \ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 @@ -287,7 +306,7 @@ local unsigned long crc32_little(crc, buf, len) local unsigned long crc32_big(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - unsigned len; + z_size_t len; { register z_crc_t c; register const z_crc_t FAR *buf4; @@ -300,7 +319,6 @@ local unsigned long crc32_big(crc, buf, len) } buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - buf4--; while (len >= 32) { DOBIG32; len -= 32; @@ -309,7 +327,6 @@ local unsigned long crc32_big(crc, buf, len) DOBIG4; len -= 4; } - buf4++; buf = (const unsigned char FAR *)buf4; if (len) do { diff --git a/3rdparty/zlib/deflate.c b/3rdparty/zlib/deflate.c index 696957705b..1ec761448d 100644 --- a/3rdparty/zlib/deflate.c +++ b/3rdparty/zlib/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; + " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -73,6 +73,8 @@ typedef enum { typedef block_state (*compress_func) OF((deflate_state *s, int flush)); /* Compression function. Returns the block state after the call. */ +local int deflateStateCheck OF((z_streamp strm)); +local void slide_hash OF((deflate_state *s)); local void fill_window OF((deflate_state *s)); local block_state deflate_stored OF((deflate_state *s, int flush)); local block_state deflate_fast OF((deflate_state *s, int flush)); @@ -84,15 +86,16 @@ local block_state deflate_huff OF((deflate_state *s, int flush)); local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifdef ASMV +# pragma message("Assembler code may have bugs -- use at your own risk") void match_init OF((void)); /* asm code initialization */ uInt longest_match OF((deflate_state *s, IPos cur_match)); #else local uInt longest_match OF((deflate_state *s, IPos cur_match)); #endif -#ifdef DEBUG +#ifdef ZLIB_DEBUG local void check_match OF((deflate_state *s, IPos start, IPos match, int length)); #endif @@ -148,21 +151,14 @@ local const config configuration_table[10] = { * meaning. */ -#define EQUAL 0 -/* result of memcmp for equal strings */ - -#ifndef NO_DUMMY_DECL -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -#endif - /* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ -#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) +#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) /* =========================================================================== * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. + * IN assertion: all calls to UPDATE_HASH are made with consecutive input + * characters, so that a running hash key can be computed from the previous + * key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) @@ -173,9 +169,9 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). + * IN assertion: all calls to INSERT_STRING are made with consecutive input + * characters and the first MIN_MATCH bytes of str are valid (except for + * the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ @@ -197,6 +193,37 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ s->head[s->hash_size-1] = NIL; \ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); +/* =========================================================================== + * Slide the hash table when sliding the window down (could be avoided with 32 + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ +local void slide_hash(s) + deflate_state *s; +{ + unsigned n, m; + Posf *p; + uInt wsize = s->w_size; + + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + } while (--n); + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif +} + /* ========================================================================= */ int ZEXPORT deflateInit_(strm, level, version, stream_size) z_streamp strm; @@ -270,7 +297,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { + strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ @@ -278,14 +305,15 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state FAR *)s; s->strm = strm; + s->status = INIT_STATE; /* to pass state test in deflateReset() */ s->wrap = wrap; s->gzhead = Z_NULL; - s->w_bits = windowBits; + s->w_bits = (uInt)windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; - s->hash_bits = memLevel + 7; + s->hash_bits = (uInt)memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); @@ -319,6 +347,31 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, return deflateReset(strm); } +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. + */ +local int deflateStateCheck (strm) + z_streamp strm; +{ + deflate_state *s; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + s = strm->state; + if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && +#ifdef GZIP + s->status != GZIP_STATE && +#endif + s->status != EXTRA_STATE && + s->status != NAME_STATE && + s->status != COMMENT_STATE && + s->status != HCRC_STATE && + s->status != BUSY_STATE && + s->status != FINISH_STATE)) + return 1; + return 0; +} + /* ========================================================================= */ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) z_streamp strm; @@ -331,7 +384,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) unsigned avail; z_const unsigned char *next; - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) + if (deflateStateCheck(strm) || dictionary == Z_NULL) return Z_STREAM_ERROR; s = strm->state; wrap = s->wrap; @@ -388,14 +441,35 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) return Z_OK; } +/* ========================================================================= */ +int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) + z_streamp strm; + Bytef *dictionary; + uInt *dictLength; +{ + deflate_state *s; + uInt len; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + len = s->strstart + s->lookahead; + if (len > s->w_size) + len = s->w_size; + if (dictionary != Z_NULL && len) + zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); + if (dictLength != Z_NULL) + *dictLength = len; + return Z_OK; +} + /* ========================================================================= */ int ZEXPORT deflateResetKeep (strm) z_streamp strm; { deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + if (deflateStateCheck(strm)) { return Z_STREAM_ERROR; } @@ -410,7 +484,11 @@ int ZEXPORT deflateResetKeep (strm) if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } - s->status = s->wrap ? INIT_STATE : BUSY_STATE; + s->status = +#ifdef GZIP + s->wrap == 2 ? GZIP_STATE : +#endif + s->wrap ? INIT_STATE : BUSY_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : @@ -440,8 +518,8 @@ int ZEXPORT deflateSetHeader (strm, head) z_streamp strm; gz_headerp head; { - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (strm->state->wrap != 2) return Z_STREAM_ERROR; + if (deflateStateCheck(strm) || strm->state->wrap != 2) + return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; } @@ -452,7 +530,7 @@ int ZEXPORT deflatePending (strm, pending, bits) int *bits; z_streamp strm; { - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; if (pending != Z_NULL) *pending = strm->state->pending; if (bits != Z_NULL) @@ -469,7 +547,7 @@ int ZEXPORT deflatePrime (strm, bits, value) deflate_state *s; int put; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; @@ -494,9 +572,8 @@ int ZEXPORT deflateParams(strm, level, strategy) { deflate_state *s; compress_func func; - int err = Z_OK; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; #ifdef FASTEST @@ -510,13 +587,22 @@ int ZEXPORT deflateParams(strm, level, strategy) func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && - strm->total_in != 0) { + s->high_water) { /* Flush the last buffer: */ - err = deflate(strm, Z_BLOCK); - if (err == Z_BUF_ERROR && s->pending == 0) - err = Z_OK; + int err = deflate(strm, Z_BLOCK); + if (err == Z_STREAM_ERROR) + return err; + if (strm->avail_out == 0) + return Z_BUF_ERROR; } if (s->level != level) { + if (s->level == 0 && s->matches != 0) { + if (s->matches == 1) + slide_hash(s); + else + CLEAR_HASH(s); + s->matches = 0; + } s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; @@ -524,7 +610,7 @@ int ZEXPORT deflateParams(strm, level, strategy) s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; - return err; + return Z_OK; } /* ========================================================================= */ @@ -537,12 +623,12 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) { deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; - s->good_match = good_length; - s->max_lazy_match = max_lazy; + s->good_match = (uInt)good_length; + s->max_lazy_match = (uInt)max_lazy; s->nice_match = nice_length; - s->max_chain_length = max_chain; + s->max_chain_length = (uInt)max_chain; return Z_OK; } @@ -569,14 +655,13 @@ uLong ZEXPORT deflateBound(strm, sourceLen) { deflate_state *s; uLong complen, wraplen; - Bytef *str; /* conservative upper bound for compressed data */ complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; /* if can't get parameters, return conservative bound plus zlib wrapper */ - if (strm == Z_NULL || strm->state == Z_NULL) + if (deflateStateCheck(strm)) return complen + 6; /* compute wrapper length */ @@ -588,9 +673,11 @@ uLong ZEXPORT deflateBound(strm, sourceLen) case 1: /* zlib wrapper */ wraplen = 6 + (s->strstart ? 4 : 0); break; +#ifdef GZIP case 2: /* gzip wrapper */ wraplen = 18; if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + Bytef *str; if (s->gzhead->extra != Z_NULL) wraplen += 2 + s->gzhead->extra_len; str = s->gzhead->name; @@ -607,6 +694,7 @@ uLong ZEXPORT deflateBound(strm, sourceLen) wraplen += 2; } break; +#endif default: /* for compiler happiness */ wraplen = 6; } @@ -634,10 +722,10 @@ local void putShortMSB (s, b) } /* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). + * Flush as much pending output as possible. All deflate() output, except for + * some deflate_stored() output, goes through this function so some + * applications may wish to modify it to avoid allocating a large + * strm->next_out buffer and copying into it. (See also read_buf()). */ local void flush_pending(strm) z_streamp strm; @@ -654,13 +742,23 @@ local void flush_pending(strm) strm->next_out += len; s->pending_out += len; strm->total_out += len; - strm->avail_out -= len; - s->pending -= len; + strm->avail_out -= len; + s->pending -= len; if (s->pending == 0) { s->pending_out = s->pending_buf; } } +/* =========================================================================== + * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. + */ +#define HCRC_UPDATE(beg) \ + do { \ + if (s->gzhead->hcrc && s->pending > (beg)) \ + strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ + s->pending - (beg)); \ + } while (0) + /* ========================================================================= */ int ZEXPORT deflate (strm, flush) z_streamp strm; @@ -669,203 +767,21 @@ int ZEXPORT deflate (strm, flush) int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_BLOCK || flush < 0) { + if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || + (strm->avail_in != 0 && strm->next_in == Z_NULL) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - s->strm = strm; /* just in case */ old_flush = s->last_flush; s->last_flush = flush; - /* Write the header */ - if (s->status == INIT_STATE) { -#ifdef GZIP - if (s->wrap == 2) { - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == Z_NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != Z_NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - else -#endif - { - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - } - } -#ifdef GZIP - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - - while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) - break; - } - put_byte(s, s->gzhead->extra[s->gzindex]); - s->gzindex++; - } - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (s->gzindex == s->gzhead->extra_len) { - s->gzindex = 0; - s->status = NAME_STATE; - } - } - else - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) { - s->gzindex = 0; - s->status = COMMENT_STATE; - } - } - else - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) - s->status = HCRC_STATE; - } - else - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) - flush_pending(strm); - if (s->pending + 2 <= s->pending_buf_size) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - } - } - else - s->status = BUSY_STATE; - } -#endif - /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); @@ -894,15 +810,197 @@ int ZEXPORT deflate (strm, flush) ERR_RETURN(strm, Z_BUF_ERROR); } + /* Write the header */ + if (s->status == INIT_STATE) { + /* zlib header */ + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#ifdef GZIP + if (s->status == GZIP_STATE) { + /* gzip header */ + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; + while (s->pending + left > s->pending_buf_size) { + uInt copy = s->pending_buf_size - s->pending; + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, copy); + s->pending = s->pending_buf_size; + HCRC_UPDATE(beg); + s->gzindex += copy; + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + left -= copy; + } + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, left); + s->pending += left; + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + } + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) { + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + } + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#endif + /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; - bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : - (s->strategy == Z_RLE ? deflate_rle(s, flush) : - (*(configuration_table[s->level].func))(s, flush)); + bstate = s->level == 0 ? deflate_stored(s, flush) : + s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; @@ -944,7 +1042,6 @@ int ZEXPORT deflate (strm, flush) } } } - Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (s->wrap <= 0) return Z_STREAM_END; @@ -981,18 +1078,9 @@ int ZEXPORT deflateEnd (strm) { int status; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); @@ -1023,7 +1111,7 @@ int ZEXPORT deflateCopy (dest, source) ushf *overlay; - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + if (deflateStateCheck(source) || dest == Z_NULL) { return Z_STREAM_ERROR; } @@ -1073,7 +1161,7 @@ int ZEXPORT deflateCopy (dest, source) * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ -local int read_buf(strm, buf, size) +local unsigned read_buf(strm, buf, size) z_streamp strm; Bytef *buf; unsigned size; @@ -1097,7 +1185,7 @@ local int read_buf(strm, buf, size) strm->next_in += len; strm->total_in += len; - return (int)len; + return len; } /* =========================================================================== @@ -1151,9 +1239,9 @@ local uInt longest_match(s, cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ + register Bytef *match; /* matched string */ register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ + int best_len = (int)s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; @@ -1188,7 +1276,7 @@ local uInt longest_match(s, cur_match) /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); @@ -1349,7 +1437,11 @@ local uInt longest_match(s, cur_match) #endif /* FASTEST */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG + +#define EQUAL 0 +/* result of memcmp for equal strings */ + /* =========================================================================== * Check that the match at match_start is indeed a match. */ @@ -1375,7 +1467,7 @@ local void check_match(s, start, match, length) } #else # define check_match(s, start, match, length) -#endif /* DEBUG */ +#endif /* ZLIB_DEBUG */ /* =========================================================================== * Fill the window when the lookahead becomes insufficient. @@ -1390,8 +1482,7 @@ local void check_match(s, start, match, length) local void fill_window(s) deflate_state *s; { - register unsigned n, m; - register Posf *p; + unsigned n; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; @@ -1418,35 +1509,11 @@ local void fill_window(s) */ if (s->strstart >= wsize+MAX_DIST(s)) { - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif + slide_hash(s); more += wsize; } if (s->strm->avail_in == 0) break; @@ -1552,70 +1619,199 @@ local void fill_window(s) if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ } +/* Maximum stored block length in deflate format (not including header). */ +#define MAX_STORED 65535 + +/* Minimum of a and b. */ +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. + * + * In case deflateParams() is used to later switch to a non-zero compression + * level, s->matches (otherwise unused when storing) keeps track of the number + * of hash table slides to perform. If s->matches is 1, then one hash table + * slide will be done when switching. If s->matches is 2, the maximum value + * allowed here, then the hash table will be cleared, since two or more slides + * is the same as a clear. + * + * deflate_stored() is written to minimize the number of times an input byte is + * copied. It is most efficient with large input and output buffers, which + * maximizes the opportunites to have a single copy from next_in to next_out. */ local block_state deflate_stored(s, flush) deflate_state *s; int flush; { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: + /* Smallest worthy block size when not flushing or finishing. By default + * this is 32K. This can be as small as 507 bytes for memLevel == 1. For + * large input and output buffers, the stored block size will be larger. */ - ulg max_block_size = 0xffff; - ulg max_start; + unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: + /* Copy as many min_block or larger stored blocks directly to next_out as + * possible. If flushing, copy the remaining available input to next_out as + * stored blocks, if there is enough space. + */ + unsigned len, left, have, last = 0; + unsigned used = s->strm->avail_in; + do { + /* Set len to the maximum size block that we can copy directly with the + * available input data and output space. Set left to how much of that + * would be copied from what's left in the window. */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); + len = MAX_STORED; /* maximum deflate stored block length */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + if (s->strm->avail_out < have) /* need room for header */ + break; + /* maximum stored block length that will fit in avail_out: */ + have = s->strm->avail_out - have; + left = s->strstart - s->block_start; /* bytes left in window */ + if (len > (ulg)left + s->strm->avail_in) + len = left + s->strm->avail_in; /* limit len to the input */ + if (len > have) + len = have; /* limit len to the output */ + + /* If the stored block would be less than min_block in length, or if + * unable to copy all of the available input when flushing, then try + * copying to the window and the pending buffer instead. Also don't + * write an empty block when flushing -- deflate() does that. + */ + if (len < min_block && ((len == 0 && flush != Z_FINISH) || + flush == Z_NO_FLUSH || + len != left + s->strm->avail_in)) + break; + + /* Make a dummy stored block in pending to get the header bytes, + * including any pending bits. This also updates the debugging counts. + */ + last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; + _tr_stored_block(s, (char *)0, 0L, last); + + /* Replace the lengths in the dummy stored block with len. */ + s->pending_buf[s->pending - 4] = len; + s->pending_buf[s->pending - 3] = len >> 8; + s->pending_buf[s->pending - 2] = ~len; + s->pending_buf[s->pending - 1] = ~len >> 8; + + /* Write the stored block header bytes. */ + flush_pending(s->strm); + +#ifdef ZLIB_DEBUG + /* Update debugging counts for the data about to be copied. */ + s->compressed_len += len << 3; + s->bits_sent += len << 3; +#endif + + /* Copy uncompressed bytes from the window to next_out. */ + if (left) { + if (left > len) + left = len; + zmemcpy(s->strm->next_out, s->window + s->block_start, left); + s->strm->next_out += left; + s->strm->avail_out -= left; + s->strm->total_out += left; + s->block_start += left; + len -= left; } + + /* Copy uncompressed bytes directly from next_in to next_out, updating + * the check value. + */ + if (len) { + read_buf(s->strm, s->strm->next_out, len); + s->strm->next_out += len; + s->strm->avail_out -= len; + s->strm->total_out += len; + } + } while (last == 0); + + /* Update the sliding window with the last s->w_size bytes of the copied + * data, or append all of the copied data to the existing window if less + * than s->w_size bytes were copied. Also update the number of bytes to + * insert in the hash tables, in the event that deflateParams() switches to + * a non-zero compression level. + */ + used -= s->strm->avail_in; /* number of input bytes directly copied */ + if (used) { + /* If any input was used, then no unused input remains in the window, + * therefore s->block_start == s->strstart. + */ + if (used >= s->w_size) { /* supplant the previous history */ + s->matches = 2; /* clear hash */ + zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); + s->strstart = s->w_size; + } + else { + if (s->window_size - s->strstart <= used) { + /* Slide the window down. */ + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + } + zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); + s->strstart += used; + } + s->block_start = s->strstart; + s->insert += MIN(used, s->w_size - s->insert); } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* If the last block was written to next_out, then done. */ + if (last) return finish_done; + + /* If flushing and all input has been consumed, then done. */ + if (flush != Z_NO_FLUSH && flush != Z_FINISH && + s->strm->avail_in == 0 && (long)s->strstart == s->block_start) + return block_done; + + /* Fill the window with any remaining input. */ + have = s->window_size - s->strstart - 1; + if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { + /* Slide the window down. */ + s->block_start -= s->w_size; + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + have += s->w_size; /* more space now */ } - if ((long)s->strstart > s->block_start) - FLUSH_BLOCK(s, 0); - return block_done; + if (have > s->strm->avail_in) + have = s->strm->avail_in; + if (have) { + read_buf(s->strm, s->window + s->strstart, have); + s->strstart += have; + } + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* There was not enough avail_out to write a complete worthy or flushed + * stored block to next_out. Write a stored block to pending instead, if we + * have enough input for a worthy block, or if flushing and there is enough + * room for the remaining input as a stored block in the pending buffer. + */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + /* maximum stored block length that will fit in pending: */ + have = MIN(s->pending_buf_size - have, MAX_STORED); + min_block = MIN(have, s->w_size); + left = s->strstart - s->block_start; + if (left >= min_block || + ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && + s->strm->avail_in == 0 && left <= have)) { + len = MIN(left, have); + last = flush == Z_FINISH && s->strm->avail_in == 0 && + len == left ? 1 : 0; + _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); + s->block_start += len; + flush_pending(s->strm); + } + + /* We've done all we can with the available input and output. */ + return last ? finish_started : need_more; } /* =========================================================================== @@ -1892,7 +2088,7 @@ local block_state deflate_rle(s, flush) prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); - s->match_length = MAX_MATCH - (int)(strend - scan); + s->match_length = MAX_MATCH - (uInt)(strend - scan); if (s->match_length > s->lookahead) s->match_length = s->lookahead; } diff --git a/3rdparty/zlib/deflate.h b/3rdparty/zlib/deflate.h index ce0299edd1..23ecdd312b 100644 --- a/3rdparty/zlib/deflate.h +++ b/3rdparty/zlib/deflate.h @@ -1,5 +1,5 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-2012 Jean-loup Gailly + * Copyright (C) 1995-2016 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -51,13 +51,16 @@ #define Buf_size 16 /* size of bit buffer in bi_buf */ -#define INIT_STATE 42 -#define EXTRA_STATE 69 -#define NAME_STATE 73 -#define COMMENT_STATE 91 -#define HCRC_STATE 103 -#define BUSY_STATE 113 -#define FINISH_STATE 666 +#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ +#ifdef GZIP +# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ +#endif +#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ +#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ +#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ +#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ +#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ +#define FINISH_STATE 666 /* stream complete */ /* Stream status */ @@ -83,7 +86,7 @@ typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ + const static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; @@ -100,10 +103,10 @@ typedef struct internal_state { Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ - uInt pending; /* nb of bytes in the pending buffer */ + ulg pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ - uInt gzindex; /* where in extra, name, or comment */ + ulg gzindex; /* where in extra, name, or comment */ Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ @@ -249,7 +252,7 @@ typedef struct internal_state { uInt matches; /* number of string matches in current block */ uInt insert; /* bytes at end of window left to insert */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif @@ -275,7 +278,7 @@ typedef struct internal_state { /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} +#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) @@ -309,7 +312,7 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, * used. */ -#ifndef DEBUG +#ifndef ZLIB_DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) @@ -328,8 +331,8 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, flush = (s->last_lit == s->lit_bufsize-1); \ } # define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (length); \ - ush dist = (distance); \ + { uch len = (uch)(length); \ + ush dist = (ush)(distance); \ s->d_buf[s->last_lit] = dist; \ s->l_buf[s->last_lit++] = len; \ dist--; \ diff --git a/3rdparty/zlib/gzguts.h b/3rdparty/zlib/gzguts.h index d87659d031..990a4d2514 100644 --- a/3rdparty/zlib/gzguts.h +++ b/3rdparty/zlib/gzguts.h @@ -1,5 +1,5 @@ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -25,6 +25,10 @@ # include # include #endif + +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif #include #ifdef _WIN32 @@ -35,6 +39,10 @@ # include #endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define WIDECHAR +#endif + #ifdef WINAPI_FAMILY # define open _open # define read _read @@ -95,18 +103,19 @@ # endif #endif -/* unlike snprintf (which is required in C99, yet still not supported by - Microsoft more than a decade later!), _snprintf does not guarantee null - termination of the result -- however this is only used in gzlib.c where +/* unlike snprintf (which is required in C99), _snprintf does not guarantee + null termination of the result -- however this is only used in gzlib.c where the result is assured to fit in the space provided */ -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 1900 # define snprintf _snprintf #endif #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ /* gz* functions always use library allocation functions */ #ifndef STDC @@ -170,7 +179,7 @@ typedef struct { char *path; /* path or fd for error messages */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ - unsigned char *in; /* input buffer */ + unsigned char *in; /* input buffer (double-sized when writing) */ unsigned char *out; /* output buffer (double-sized when reading) */ int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ diff --git a/3rdparty/zlib/gzlib.c b/3rdparty/zlib/gzlib.c index fae202ef89..4105e6aff9 100644 --- a/3rdparty/zlib/gzlib.c +++ b/3rdparty/zlib/gzlib.c @@ -1,11 +1,11 @@ /* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler + * Copyright (C) 2004-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" -#if defined(_WIN32) && !defined(__BORLANDC__) +#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__) # define LSEEK _lseeki64 #else #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 @@ -94,7 +94,7 @@ local gzFile gz_open(path, fd, mode) const char *mode; { gz_statep state; - size_t len; + z_size_t len; int oflag; #ifdef O_CLOEXEC int cloexec = 0; @@ -188,10 +188,10 @@ local gzFile gz_open(path, fd, mode) } /* save the path name for error messages */ -#ifdef _WIN32 +#ifdef WIDECHAR if (fd == -2) { len = wcstombs(NULL, path, 0); - if (len == (size_t)-1) + if (len == (z_size_t)-1) len = 0; } else @@ -202,7 +202,7 @@ local gzFile gz_open(path, fd, mode) free(state); return NULL; } -#ifdef _WIN32 +#ifdef WIDECHAR if (fd == -2) if (len) wcstombs(state->path, path, len + 1); @@ -211,7 +211,7 @@ local gzFile gz_open(path, fd, mode) else #endif #if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(state->path, len + 1, "%s", (const char *)path); + (void)snprintf(state->path, len + 1, "%s", (const char *)path); #else strcpy(state->path, path); #endif @@ -239,7 +239,7 @@ local gzFile gz_open(path, fd, mode) /* open the file with the appropriate flags (or just use fd) */ state->fd = fd > -1 ? fd : ( -#ifdef _WIN32 +#ifdef WIDECHAR fd == -2 ? _wopen(path, oflag, 0666) : #endif open((const char *)path, oflag, 0666)); @@ -248,8 +248,10 @@ local gzFile gz_open(path, fd, mode) free(state); return NULL; } - if (state->mode == GZ_APPEND) + if (state->mode == GZ_APPEND) { + LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ state->mode = GZ_WRITE; /* simplify later checks */ + } /* save the current position for rewinding (only if reading) */ if (state->mode == GZ_READ) { @@ -291,7 +293,7 @@ gzFile ZEXPORT gzdopen(fd, mode) if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) return NULL; #if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(path, 7 + 3 * sizeof(int), "", fd); /* for debugging */ + (void)snprintf(path, 7 + 3 * sizeof(int), "", fd); #else sprintf(path, "", fd); /* for debugging */ #endif @@ -301,7 +303,7 @@ gzFile ZEXPORT gzdopen(fd, mode) } /* -- see zlib.h -- */ -#ifdef _WIN32 +#ifdef WIDECHAR gzFile ZEXPORT gzopen_w(path, mode) const wchar_t *path; const char *mode; @@ -329,6 +331,8 @@ int ZEXPORT gzbuffer(file, size) return -1; /* check and set requested size */ + if ((size << 1) < size) + return -1; /* need to be able to double it */ if (size < 2) size = 2; /* need two bytes to check magic header */ state->want = size; @@ -604,14 +608,13 @@ void ZLIB_INTERNAL gz_error(state, err, msg) return; } #if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, - "%s%s%s", state->path, ": ", msg); + (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, + "%s%s%s", state->path, ": ", msg); #else strcpy(state->msg, state->path); strcat(state->msg, ": "); strcat(state->msg, msg); #endif - return; } #ifndef INT_MAX diff --git a/3rdparty/zlib/gzread.c b/3rdparty/zlib/gzread.c index 68ad01d993..956b91ea7d 100644 --- a/3rdparty/zlib/gzread.c +++ b/3rdparty/zlib/gzread.c @@ -1,5 +1,5 @@ /* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -12,6 +12,7 @@ local int gz_look OF((gz_statep)); local int gz_decomp OF((gz_statep)); local int gz_fetch OF((gz_statep)); local int gz_skip OF((gz_statep, z_off64_t)); +local z_size_t gz_read OF((gz_statep, voidp, z_size_t)); /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from state->fd, and update state->eof, state->err, and state->msg as appropriate. @@ -24,13 +25,17 @@ local int gz_load(state, buf, len, have) unsigned *have; { int ret; + unsigned get, max = ((unsigned)-1 >> 2) + 1; *have = 0; do { - ret = (int) read(state->fd, buf + *have, len - *have); + get = len - *have; + if (get > max) + get = max; + ret = read(state->fd, buf + *have, get); if (ret <= 0) break; - *have += ret; + *have += (unsigned)ret; } while (*have < len); if (ret < 0) { gz_error(state, Z_ERRNO, zstrerror()); @@ -94,10 +99,8 @@ local int gz_look(state) state->in = (unsigned char *)malloc(state->want); state->out = (unsigned char *)malloc(state->want << 1); if (state->in == NULL || state->out == NULL) { - if (state->out != NULL) - free(state->out); - if (state->in != NULL) - free(state->in); + free(state->out); + free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } @@ -284,33 +287,17 @@ local int gz_skip(state, len) return 0; } -/* -- see zlib.h -- */ -int ZEXPORT gzread(file, buf, len) - gzFile file; - voidp buf; - unsigned len; -{ - unsigned got, n; +/* Read len bytes into buf from file, or less than len up to the end of the + input. Return the number of bytes read. If zero is returned, either the + end of file was reached, or there was an error. state->err must be + consulted in that case to determine which. */ +local z_size_t gz_read(state, buf, len) gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return -1; - } + voidp buf; + z_size_t len; +{ + z_size_t got; + unsigned n; /* if len is zero, avoid unnecessary operations */ if (len == 0) @@ -320,32 +307,38 @@ int ZEXPORT gzread(file, buf, len) if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) - return -1; + return 0; } /* get len bytes to buf, or less than len if at the end */ got = 0; do { + /* set n to the maximum amount of len that fits in an unsigned int */ + n = -1; + if (n > len) + n = len; + /* first just try copying data from the output buffer */ if (state->x.have) { - n = state->x.have > len ? len : state->x.have; + if (state->x.have < n) + n = state->x.have; memcpy(buf, state->x.next, n); state->x.next += n; state->x.have -= n; } /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && strm->avail_in == 0) { + else if (state->eof && state->strm.avail_in == 0) { state->past = 1; /* tried to read past end */ break; } /* need output data -- for small len or new stream load up our output buffer */ - else if (state->how == LOOK || len < (state->size << 1)) { + else if (state->how == LOOK || n < (state->size << 1)) { /* get more output, looking for header if required */ if (gz_fetch(state) == -1) - return -1; + return 0; continue; /* no progress yet -- go back to copy above */ /* the copy above assures that we will leave with space in the output buffer, allowing at least one gzungetc() to succeed */ @@ -353,16 +346,16 @@ int ZEXPORT gzread(file, buf, len) /* large len -- read directly into user buffer */ else if (state->how == COPY) { /* read directly */ - if (gz_load(state, (unsigned char *)buf, len, &n) == -1) - return -1; + if (gz_load(state, (unsigned char *)buf, n, &n) == -1) + return 0; } /* large len -- decompress directly into user buffer */ else { /* state->how == GZIP */ - strm->avail_out = len; - strm->next_out = (unsigned char *)buf; + state->strm.avail_out = n; + state->strm.next_out = (unsigned char *)buf; if (gz_decomp(state) == -1) - return -1; + return 0; n = state->x.have; state->x.have = 0; } @@ -374,8 +367,75 @@ int ZEXPORT gzread(file, buf, len) state->x.pos += n; } while (len); - /* return number of bytes read into user buffer (will fit in int) */ - return (int)got; + /* return number of bytes read into user buffer */ + return got; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzread(file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); + return -1; + } + + /* read len or fewer bytes to buf */ + len = gz_read(state, buf, len); + + /* check for an error */ + if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + + /* return the number of bytes read (this is assured to fit in an int) */ + return (int)len; +} + +/* -- see zlib.h -- */ +z_size_t ZEXPORT gzfread(buf, size, nitems, file) + voidp buf; + z_size_t size; + z_size_t nitems; + gzFile file; +{ + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return 0; + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* read len or fewer bytes to buf, return the number of full items read */ + return len ? gz_read(state, buf, len) / size : 0; } /* -- see zlib.h -- */ @@ -408,8 +468,8 @@ int ZEXPORT gzgetc(file) return *(state->x.next)++; } - /* nothing there -- try gzread() */ - ret = gzread(file, buf, 1); + /* nothing there -- try gz_read() */ + ret = gz_read(state, buf, 1); return ret < 1 ? -1 : buf[0]; } @@ -451,7 +511,7 @@ int ZEXPORT gzungetc(c, file) if (state->x.have == 0) { state->x.have = 1; state->x.next = state->out + (state->size << 1) - 1; - state->x.next[0] = c; + state->x.next[0] = (unsigned char)c; state->x.pos--; state->past = 0; return c; @@ -473,7 +533,7 @@ int ZEXPORT gzungetc(c, file) } state->x.have++; state->x.next--; - state->x.next[0] = c; + state->x.next[0] = (unsigned char)c; state->x.pos--; state->past = 0; return c; diff --git a/3rdparty/zlib/gzwrite.c b/3rdparty/zlib/gzwrite.c index e9525417c8..c7b5651d70 100644 --- a/3rdparty/zlib/gzwrite.c +++ b/3rdparty/zlib/gzwrite.c @@ -1,5 +1,5 @@ /* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler + * Copyright (C) 2004-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,17 +9,19 @@ local int gz_init OF((gz_statep)); local int gz_comp OF((gz_statep, int)); local int gz_zero OF((gz_statep, z_off64_t)); +local z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); /* Initialize state for writing a gzip file. Mark initialization by setting - state->size to non-zero. Return -1 on failure or 0 on success. */ + state->size to non-zero. Return -1 on a memory allocation failure, or 0 on + success. */ local int gz_init(state) gz_statep state; { int ret; z_streamp strm = &(state->strm); - /* allocate input buffer */ - state->in = (unsigned char *)malloc(state->want); + /* allocate input buffer (double size for gzprintf) */ + state->in = (unsigned char *)malloc(state->want << 1); if (state->in == NULL) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; @@ -47,6 +49,7 @@ local int gz_init(state) gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } + strm->next_in = NULL; } /* mark state as initialized */ @@ -62,17 +65,17 @@ local int gz_init(state) } /* Compress whatever is at avail_in and next_in and write to the output file. - Return -1 if there is an error writing to the output file, otherwise 0. - flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, - then the deflate() state is reset to start a new gzip stream. If gz->direct - is true, then simply write to the output file without compressing, and - ignore flush. */ + Return -1 if there is an error writing to the output file or if gz_init() + fails to allocate memory, otherwise 0. flush is assumed to be a valid + deflate() flush value. If flush is Z_FINISH, then the deflate() state is + reset to start a new gzip stream. If gz->direct is true, then simply write + to the output file without compressing, and ignore flush. */ local int gz_comp(state, flush) gz_statep state; int flush; { - int ret, got; - unsigned have; + int ret, writ; + unsigned have, put, max = ((unsigned)-1 >> 2) + 1; z_streamp strm = &(state->strm); /* allocate memory if this is the first time through */ @@ -81,12 +84,16 @@ local int gz_comp(state, flush) /* write directly if requested */ if (state->direct) { - got = (int) write(state->fd, strm->next_in, strm->avail_in); - if (got < 0 || (unsigned)got != strm->avail_in) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; + while (strm->avail_in) { + put = strm->avail_in > max ? max : strm->avail_in; + writ = write(state->fd, strm->next_in, put); + if (writ < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + strm->avail_in -= (unsigned)writ; + strm->next_in += writ; } - strm->avail_in = 0; return 0; } @@ -97,17 +104,21 @@ local int gz_comp(state, flush) doing Z_FINISH then don't write until we get to Z_STREAM_END */ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { - have = (unsigned)(strm->next_out - state->x.next); - if (have && ((got = (int) write(state->fd, state->x.next, have)) < 0 || - (unsigned)got != have)) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; + while (strm->next_out > state->x.next) { + put = strm->next_out - state->x.next > (int)max ? max : + (unsigned)(strm->next_out - state->x.next); + writ = write(state->fd, state->x.next, put); + if (writ < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + state->x.next += writ; } if (strm->avail_out == 0) { strm->avail_out = state->size; strm->next_out = state->out; + state->x.next = state->out; } - state->x.next = strm->next_out; } /* compress */ @@ -129,7 +140,8 @@ local int gz_comp(state, flush) return 0; } -/* Compress len zeros to output. Return -1 on error, 0 on success. */ +/* Compress len zeros to output. Return -1 on a write error or memory + allocation failure by gz_comp(), or 0 on success. */ local int gz_zero(state, len) gz_statep state; z_off64_t len; @@ -161,32 +173,14 @@ local int gz_zero(state, len) return 0; } -/* -- see zlib.h -- */ -int ZEXPORT gzwrite(file, buf, len) - gzFile file; - voidpc buf; - unsigned len; -{ - unsigned put = len; +/* Write len bytes from buf to file. Return the number of bytes written. If + the returned value is less than len, then there was an error. */ +local z_size_t gz_write(state, buf, len) gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return 0; - } + voidpc buf; + z_size_t len; +{ + z_size_t put = len; /* if len is zero, avoid unnecessary operations */ if (len == 0) @@ -209,14 +203,15 @@ int ZEXPORT gzwrite(file, buf, len) do { unsigned have, copy; - if (strm->avail_in == 0) - strm->next_in = state->in; - have = (unsigned)((strm->next_in + strm->avail_in) - state->in); + if (state->strm.avail_in == 0) + state->strm.next_in = state->in; + have = (unsigned)((state->strm.next_in + state->strm.avail_in) - + state->in); copy = state->size - have; if (copy > len) copy = len; memcpy(state->in + have, buf, copy); - strm->avail_in += copy; + state->strm.avail_in += copy; state->x.pos += copy; buf = (const char *)buf + copy; len -= copy; @@ -226,19 +221,83 @@ int ZEXPORT gzwrite(file, buf, len) } else { /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* directly compress user buffer to file */ - strm->avail_in = len; - strm->next_in = (z_const Bytef *)buf; - state->x.pos += len; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return 0; + state->strm.next_in = (z_const Bytef *)buf; + do { + unsigned n = (unsigned)-1; + if (n > len) + n = len; + state->strm.avail_in = n; + state->x.pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + len -= n; + } while (len); } - /* input was all buffered or compressed (put will fit in int) */ - return (int)put; + /* input was all buffered or compressed */ + return put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzwrite(file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); + return 0; + } + + /* write len bytes from buf (the return value will fit in an int) */ + return (int)gz_write(state, buf, len); +} + +/* -- see zlib.h -- */ +z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) + voidpc buf; + z_size_t size; + z_size_t nitems; + gzFile file; +{ + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* write len bytes to buf, return the number of full items written */ + return len ? gz_write(state, buf, len) / size : 0; } /* -- see zlib.h -- */ @@ -275,7 +334,7 @@ int ZEXPORT gzputc(file, c) strm->next_in = state->in; have = (unsigned)((strm->next_in + strm->avail_in) - state->in); if (have < state->size) { - state->in[have] = c; + state->in[have] = (unsigned char)c; strm->avail_in++; state->x.pos++; return c & 0xff; @@ -283,8 +342,8 @@ int ZEXPORT gzputc(file, c) } /* no room in buffer or not initialized, use gz_write() */ - buf[0] = c; - if (gzwrite(file, buf, 1) != 1) + buf[0] = (unsigned char)c; + if (gz_write(state, buf, 1) != 1) return -1; return c & 0xff; } @@ -295,11 +354,21 @@ int ZEXPORT gzputs(file, str) const char *str; { int ret; - unsigned len; + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; /* write string */ - len = (unsigned)strlen(str); - ret = gzwrite(file, str, len); + len = strlen(str); + ret = gz_write(state, str, len); return ret == 0 && len != 0 ? -1 : ret; } @@ -309,63 +378,73 @@ int ZEXPORT gzputs(file, str) /* -- see zlib.h -- */ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { - int size, len; + int len; + unsigned left; + char *next; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; + return Z_STREAM_ERROR; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) - return 0; + return state->err; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return 0; + return state->err; } - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); + next[state->size - 1] = 0; #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void - (void)vsprintf((char *)(state->in), format, va); - for (len = 0; len < size; len++) - if (state->in[len] == 0) break; + (void)vsprintf(next, format, va); + for (len = 0; len < state->size; len++) + if (next[len] == 0) break; # else - len = vsprintf((char *)(state->in), format, va); + len = vsprintf(next, format, va); # endif #else # ifdef HAS_vsnprintf_void - (void)vsnprintf((char *)(state->in), size, format, va); - len = strlen((char *)(state->in)); + (void)vsnprintf(next, state->size, format, va); + len = strlen(next); # else - len = vsnprintf((char *)(state->in), size, format, va); + len = vsnprintf(next, state->size, format, va); # endif #endif /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) return 0; - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; + /* update buffer and position, compress first half if past that */ + strm->avail_in += (unsigned)len; state->x.pos += len; + if (strm->avail_in >= state->size) { + left = strm->avail_in - state->size; + strm->avail_in = state->size; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->err; + memcpy(state->in, state->in + state->size, left); + strm->next_in = state->in; + strm->avail_in = left; + } return len; } @@ -390,73 +469,82 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; { - int size, len; + unsigned len, left; + char *next; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that can really pass pointer in ints */ if (sizeof(int) != sizeof(void *)) - return 0; + return Z_STREAM_ERROR; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; + return Z_STREAM_ERROR; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) - return 0; + return state->error; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return 0; + return state->error; } - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(strm->next_in + strm->avail_in); + next[state->size - 1] = 0; #ifdef NO_snprintf # ifdef HAS_sprintf_void - sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20); for (len = 0; len < size; len++) - if (state->in[len] == 0) break; + if (next[len] == 0) + break; # else - len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, + a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #else # ifdef HAS_snprintf_void - snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen((char *)(state->in)); + snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(next); # else - len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, - a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, - a19, a20); + len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #endif /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + if (len == 0 || len >= state->size || next[state->size - 1] != 0) return 0; - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; + /* update buffer and position, compress first half if past that */ + strm->avail_in += len; state->x.pos += len; - return len; + if (strm->avail_in >= state->size) { + left = strm->avail_in - state->size; + strm->avail_in = state->size; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->err; + memcpy(state->in, state->in + state->size, left); + strm->next_in = state->in; + strm->avail_in = left; + } + return (int)len; } #endif @@ -470,7 +558,7 @@ int ZEXPORT gzflush(file, flush) /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're writing and that there's no error */ @@ -485,11 +573,11 @@ int ZEXPORT gzflush(file, flush) if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return -1; + return state->err; } /* compress remaining data with requested flush */ - gz_comp(state, flush); + (void)gz_comp(state, flush); return state->err; } @@ -520,13 +608,13 @@ int ZEXPORT gzsetparams(file, level, strategy) if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return -1; + return state->err; } /* change compression parameters for subsequent input */ if (state->size) { /* flush previous input with previous parameters before changing */ - if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) + if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) return state->err; deflateParams(strm, level, strategy); } diff --git a/3rdparty/zlib/infback.c b/3rdparty/zlib/infback.c index f3833c2e43..59679ecbfc 100644 --- a/3rdparty/zlib/infback.c +++ b/3rdparty/zlib/infback.c @@ -1,5 +1,5 @@ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -61,7 +61,7 @@ int stream_size; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->dmax = 32768U; - state->wbits = windowBits; + state->wbits = (uInt)windowBits; state->wsize = 1U << windowBits; state->window = window; state->wnext = 0; diff --git a/3rdparty/zlib/inffast.c b/3rdparty/zlib/inffast.c index bda59ceb6a..0dbd1dbc09 100644 --- a/3rdparty/zlib/inffast.c +++ b/3rdparty/zlib/inffast.c @@ -1,5 +1,5 @@ /* inffast.c -- fast decoding - * Copyright (C) 1995-2008, 2010, 2013 Mark Adler + * Copyright (C) 1995-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -8,26 +8,9 @@ #include "inflate.h" #include "inffast.h" -#ifndef ASMINF - -/* Allow machine dependent optimization for post-increment or pre-increment. - Based on testing to date, - Pre-increment preferred for: - - PowerPC G3 (Adler) - - MIPS R5000 (Randers-Pehrson) - Post-increment preferred for: - - none - No measurable difference: - - Pentium III (Anderson) - - M68060 (Nikl) - */ -#ifdef POSTINC -# define OFF 0 -# define PUP(a) *(a)++ +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") #else -# define OFF 1 -# define PUP(a) *++(a) -#endif /* Decode literal, length, and distance codes and write out the resulting @@ -96,9 +79,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; - in = strm->next_in - OFF; + in = strm->next_in; last = in + (strm->avail_in - 5); - out = strm->next_out - OFF; + out = strm->next_out; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT @@ -119,9 +102,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ input data or output space */ do { if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } here = lcode[hold & lmask]; @@ -134,14 +117,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); - PUP(out) = (unsigned char)(here.val); + *out++ = (unsigned char)(here.val); } else if (op & 16) { /* length base */ len = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); @@ -150,9 +133,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } here = dcode[hold & dmask]; @@ -165,10 +148,10 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ dist = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } } @@ -196,30 +179,30 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { - PUP(out) = 0; + *out++ = 0; } while (--len); continue; } len -= op - whave; do { - PUP(out) = 0; + *out++ = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--len); continue; } #endif } - from = window - OFF; + from = window; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } @@ -230,14 +213,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ if (op < len) { /* some from end of window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); - from = window - OFF; + from = window; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } @@ -248,35 +231,35 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; len -= 3; } if (len) { - PUP(out) = PUP(from); + *out++ = *from++; if (len > 1) - PUP(out) = PUP(from); + *out++ = *from++; } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; len -= 3; } while (len > 2); if (len) { - PUP(out) = PUP(from); + *out++ = *from++; if (len > 1) - PUP(out) = PUP(from); + *out++ = *from++; } } } @@ -313,8 +296,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ hold &= (1U << bits) - 1; /* update state and return */ - strm->next_in = in + OFF; - strm->next_out = out + OFF; + strm->next_in = in; + strm->next_out = out; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); diff --git a/3rdparty/zlib/inflate.c b/3rdparty/zlib/inflate.c index 870f89bb4d..ac333e8c2e 100644 --- a/3rdparty/zlib/inflate.c +++ b/3rdparty/zlib/inflate.c @@ -1,5 +1,5 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2012 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -92,6 +92,7 @@ #endif /* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); local void fixedtables OF((struct inflate_state FAR *state)); local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, unsigned copy)); @@ -101,12 +102,26 @@ local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, unsigned len)); +local int inflateStateCheck(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + int ZEXPORT inflateResetKeep(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; @@ -131,7 +146,7 @@ z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; state->wsize = 0; state->whave = 0; @@ -147,7 +162,7 @@ int windowBits; struct inflate_state FAR *state; /* get the state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* extract wrap request from windowBits parameter */ @@ -156,7 +171,7 @@ int windowBits; windowBits = -windowBits; } else { - wrap = (windowBits >> 4) + 1; + wrap = (windowBits >> 4) + 5; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; @@ -210,7 +225,9 @@ int stream_size; if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; + state->strm = strm; state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); @@ -234,17 +251,17 @@ int value; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; state->bits = 0; return Z_OK; } - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; - state->hold += value << state->bits; - state->bits += bits; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; return Z_OK; } @@ -625,7 +642,7 @@ int flush; static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; @@ -645,6 +662,8 @@ int flush; NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); @@ -672,7 +691,7 @@ int flush; len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; - else if (len > state->wbits) { + if (len > 15 || len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; @@ -699,14 +718,16 @@ int flush; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); state->mode = TIME; case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; - if (state->flags & 0x0200) CRC4(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); INITBITS(); state->mode = OS; case OS: @@ -715,7 +736,8 @@ int flush; state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; case EXLEN: @@ -724,7 +746,8 @@ int flush; state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) @@ -742,7 +765,7 @@ int flush; len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -761,9 +784,9 @@ int flush; if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) - state->head->name[state->length++] = len; + state->head->name[state->length++] = (Bytef)len; } while (len && copy < have); - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -782,9 +805,9 @@ int flush; if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) - state->head->comment[state->length++] = len; + state->head->comment[state->length++] = (Bytef)len; } while (len && copy < have); - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -796,7 +819,7 @@ int flush; case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); - if (hold != (state->check & 0xffff)) { + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; @@ -1177,11 +1200,11 @@ int flush; out -= left; strm->total_out += out; state->total += out; - if (out) + if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE(state->check, put - out, out); out = left; - if (( + if ((state->wrap & 4) && ( #ifdef GUNZIP state->flags ? hold : #endif @@ -1240,10 +1263,10 @@ int flush; strm->total_in += in; strm->total_out += out; state->total += out; - if (state->wrap && out) + if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); - strm->data_type = state->bits + (state->last ? 64 : 0) + + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) @@ -1255,7 +1278,7 @@ int ZEXPORT inflateEnd(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); @@ -1273,7 +1296,7 @@ uInt *dictLength; struct inflate_state FAR *state; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* copy dictionary */ @@ -1298,7 +1321,7 @@ uInt dictLength; int ret; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; @@ -1330,7 +1353,7 @@ gz_headerp head; struct inflate_state FAR *state; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; @@ -1383,7 +1406,7 @@ z_streamp strm; struct inflate_state FAR *state; /* check parameters */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; @@ -1430,7 +1453,7 @@ z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; return state->mode == STORED && state->bits == 0; } @@ -1445,8 +1468,7 @@ z_streamp source; unsigned wsize; /* check input */ - if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || - source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + if (inflateStateCheck(source) || dest == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)source->state; @@ -1467,6 +1489,7 @@ z_streamp source; /* copy state */ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); @@ -1488,25 +1511,51 @@ int subvert; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; - state->sane = !subvert; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; return Z_OK; #else + (void)subvert; state->sane = 1; return Z_DATA_ERROR; #endif } +int ZEXPORT inflateValidate(strm, check) +z_streamp strm; +int check; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + long ZEXPORT inflateMark(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + if (inflateStateCheck(strm)) + return -(1L << 16); state = (struct inflate_state FAR *)strm->state; - return ((long)(state->back) << 16) + + return (long)(((unsigned long)((long)state->back)) << 16) + (state->mode == COPY ? state->length : (state->mode == MATCH ? state->was - state->length : 0)); } + +unsigned long ZEXPORT inflateCodesUsed(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} diff --git a/3rdparty/zlib/inflate.h b/3rdparty/zlib/inflate.h index 95f4986d40..a46cce6b6d 100644 --- a/3rdparty/zlib/inflate.h +++ b/3rdparty/zlib/inflate.h @@ -1,5 +1,5 @@ /* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2009 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -18,7 +18,7 @@ /* Possible inflate modes between inflate() calls */ typedef enum { - HEAD, /* i: waiting for magic header */ + HEAD = 16180, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ @@ -77,11 +77,14 @@ typedef enum { CHECK -> LENGTH -> DONE */ -/* state maintained between inflate() calls. Approximately 10K bytes. */ +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags (0 if zlib) */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ diff --git a/3rdparty/zlib/inftrees.c b/3rdparty/zlib/inftrees.c index 44d89cf24e..2ea08fc13e 100644 --- a/3rdparty/zlib/inftrees.c +++ b/3rdparty/zlib/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2013 Mark Adler + * Copyright (C) 1995-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.8 Copyright 1995-2013 Mark Adler "; + " inflate 1.2.11 Copyright 1995-2017 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -54,7 +54,7 @@ unsigned short FAR *work; code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ + unsigned match; /* use base and extra for symbol >= match */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ @@ -62,7 +62,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, @@ -181,19 +181,17 @@ unsigned short FAR *work; switch (type) { case CODES: base = extra = work; /* dummy value--not used */ - end = 19; + match = 20; break; case LENS: base = lbase; - base -= 257; extra = lext; - extra -= 257; - end = 256; + match = 257; break; - default: /* DISTS */ + default: /* DISTS */ base = dbase; extra = dext; - end = -1; + match = 0; } /* initialize state for loop */ @@ -216,13 +214,13 @@ unsigned short FAR *work; for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { + if (work[sym] + 1U < match) { here.op = (unsigned char)0; here.val = work[sym]; } - else if ((int)(work[sym]) > end) { - here.op = (unsigned char)(extra[work[sym]]); - here.val = base[work[sym]]; + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ diff --git a/3rdparty/zlib/trees.c b/3rdparty/zlib/trees.c index 1fd7759ef0..50cf4b4571 100644 --- a/3rdparty/zlib/trees.c +++ b/3rdparty/zlib/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2012 Jean-loup Gailly + * Copyright (C) 1995-2017 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -36,7 +36,7 @@ #include "deflate.h" -#ifdef DEBUG +#ifdef ZLIB_DEBUG # include #endif @@ -122,13 +122,13 @@ struct static_tree_desc_s { int max_length; /* max bit length for the codes */ }; -local static_tree_desc static_l_desc = +local const static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; -local static_tree_desc static_d_desc = +local const static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; -local static_tree_desc static_bl_desc = +local const static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== @@ -152,18 +152,16 @@ local int detect_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); #ifdef GEN_TREES_H local void gen_trees_header OF((void)); #endif -#ifndef DEBUG +#ifndef ZLIB_DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ -#else /* DEBUG */ +#else /* !ZLIB_DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } @@ -182,7 +180,7 @@ local void gen_trees_header OF((void)); * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG local void send_bits OF((deflate_state *s, int value, int length)); local void send_bits(s, value, length) @@ -208,12 +206,12 @@ local void send_bits(s, value, length) s->bi_valid += length; } } -#else /* !DEBUG */ +#else /* !ZLIB_DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ + int val = (int)value;\ s->bi_buf |= (ush)val << s->bi_valid;\ put_short(s, s->bi_buf);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ @@ -223,7 +221,7 @@ local void send_bits(s, value, length) s->bi_valid += len;\ }\ } -#endif /* DEBUG */ +#endif /* ZLIB_DEBUG */ /* the arguments must not have side effects */ @@ -317,7 +315,7 @@ local void tr_static_init() * Genererate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H -# ifndef DEBUG +# ifndef ZLIB_DEBUG # include # endif @@ -394,7 +392,7 @@ void ZLIB_INTERNAL _tr_init(s) s->bi_buf = 0; s->bi_valid = 0; -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len = 0L; s->bits_sent = 0L; #endif @@ -522,12 +520,12 @@ local void gen_bitlen(s, desc) xbits = 0; if (n >= base) xbits = extra[n-base]; f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + s->opt_len += (ulg)f * (unsigned)(bits + xbits); + if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); } if (overflow == 0) return; - Trace((stderr,"\nbit length overflow\n")); + Tracev((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ @@ -554,9 +552,8 @@ local void gen_bitlen(s, desc) m = s->heap[--h]; if (m > max_code) continue; if ((unsigned) tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; + Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq; tree[m].Len = (ush)bits; } n--; @@ -578,7 +575,7 @@ local void gen_codes (tree, max_code, bl_count) ushf *bl_count; /* number of codes at each bit length */ { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ + unsigned code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ @@ -586,7 +583,8 @@ local void gen_codes (tree, max_code, bl_count) * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; + code = (code + bl_count[bits-1]) << 1; + next_code[bits] = (ush)code; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. @@ -599,7 +597,7 @@ local void gen_codes (tree, max_code, bl_count) int len = tree[n].Len; if (len == 0) continue; /* Now reverse the bits */ - tree[n].Code = bi_reverse(next_code[len]++, len); + tree[n].Code = (ush)bi_reverse(next_code[len]++, len); Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); @@ -821,7 +819,7 @@ local int build_bl_tree(s) if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; + s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); @@ -869,11 +867,17 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) int last; /* one if this is the last block for a file */ { send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ -#ifdef DEBUG + bi_windup(s); /* align on byte boundary */ + put_short(s, (ush)stored_len); + put_short(s, (ush)~stored_len); + zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len); + s->pending += stored_len; +#ifdef ZLIB_DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; + s->bits_sent += 2*16; + s->bits_sent += stored_len<<3; #endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } /* =========================================================================== @@ -894,7 +898,7 @@ void ZLIB_INTERNAL _tr_align(s) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); @@ -902,7 +906,7 @@ void ZLIB_INTERNAL _tr_align(s) /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. + * trees or store, and write out the encoded block. */ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) deflate_state *s; @@ -974,7 +978,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) send_bits(s, (STATIC_TREES<<1)+last, 3); compress_block(s, (const ct_data *)static_ltree, (const ct_data *)static_dtree); -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len += 3 + s->static_len; #endif } else { @@ -983,7 +987,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) max_blindex+1); compress_block(s, (const ct_data *)s->dyn_ltree, (const ct_data *)s->dyn_dtree); -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len += 3 + s->opt_len; #endif } @@ -995,7 +999,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) if (last) { bi_windup(s); -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } @@ -1090,7 +1094,7 @@ local void compress_block(s, ltree, dtree) send_code(s, code, dtree); /* send the distance code */ extra = extra_dbits[code]; if (extra != 0) { - dist -= base_dist[code]; + dist -= (unsigned)base_dist[code]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ @@ -1193,34 +1197,7 @@ local void bi_windup(s) } s->bi_buf = 0; s->bi_valid = 0; -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->bits_sent = (s->bits_sent+7) & ~7; #endif } - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -local void copy_block(s, buf, len, header) - deflate_state *s; - charf *buf; /* the input data */ - unsigned len; /* its length */ - int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} diff --git a/3rdparty/zlib/uncompr.c b/3rdparty/zlib/uncompr.c index 242e9493df..f03a1a865e 100644 --- a/3rdparty/zlib/uncompr.c +++ b/3rdparty/zlib/uncompr.c @@ -1,5 +1,5 @@ /* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. + * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,51 +9,85 @@ #include "zlib.h" /* =========================================================================== - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. + Decompresses the source buffer into the destination buffer. *sourceLen is + the byte length of the source buffer. Upon entry, *destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, + *destLen is the size of the decompressed data and *sourceLen is the number + of source bytes consumed. Upon return, source + *sourceLen points to the + first unused input byte. - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, or + Z_DATA_ERROR if the input data was corrupted, including if the input data is + an incomplete zlib stream. */ +int ZEXPORT uncompress2 (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong *sourceLen; +{ + z_stream stream; + int err; + const uInt max = (uInt)-1; + uLong len, left; + Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */ + + len = *sourceLen; + if (*destLen) { + left = *destLen; + *destLen = 0; + } + else { + left = 1; + dest = buf; + } + + stream.next_in = (z_const Bytef *)source; + stream.avail_in = 0; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + stream.next_out = dest; + stream.avail_out = 0; + + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (uLong)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = len > (uLong)max ? max : (uInt)len; + len -= stream.avail_in; + } + err = inflate(&stream, Z_NO_FLUSH); + } while (err == Z_OK); + + *sourceLen -= len + stream.avail_in; + if (dest != buf) + *destLen = stream.total_out; + else if (stream.total_out && err == Z_BUF_ERROR) + left = 1; + + inflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : + err == Z_NEED_DICT ? Z_DATA_ERROR : + err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR : + err; +} + int ZEXPORT uncompress (dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; uLong sourceLen; { - z_stream stream; - int err; - - stream.next_in = (z_const Bytef *)source; - stream.avail_in = (uInt)sourceLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; - - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - - err = inflateInit(&stream); - if (err != Z_OK) return err; - - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) - return Z_DATA_ERROR; - return err; - } - *destLen = stream.total_out; - - err = inflateEnd(&stream); - return err; + return uncompress2(dest, destLen, source, &sourceLen); } diff --git a/3rdparty/zlib/zconf.h.cmakein b/3rdparty/zlib/zconf.h similarity index 93% rename from 3rdparty/zlib/zconf.h.cmakein rename to 3rdparty/zlib/zconf.h index 6528fb4df8..5e1d68a004 100644 --- a/3rdparty/zlib/zconf.h.cmakein +++ b/3rdparty/zlib/zconf.h @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -7,8 +7,6 @@ #ifndef ZCONF_H #define ZCONF_H -#cmakedefine Z_PREFIX -#cmakedefine Z_HAVE_UNISTD_H /* * If you *really* need a unique prefix for all types and library functions, @@ -19,7 +17,7 @@ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET -/* all linked symbols */ +/* all linked symbols and init macros */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align @@ -31,6 +29,7 @@ # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z # ifndef Z_SOLO # define compress z_compress # define compress2 z_compress2 @@ -39,10 +38,14 @@ # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams @@ -69,6 +72,8 @@ # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite # define gzgetc z_gzgetc # define gzgetc_ z_gzgetc_ # define gzgets z_gzgets @@ -80,7 +85,6 @@ # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf -# define gzvprintf z_gzvprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread @@ -91,32 +95,39 @@ # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf # define gzwrite z_gzwrite # endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit # define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary # define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep # define inflateSetDictionary z_inflateSetDictionary -# define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine -# define inflateResetKeep z_inflateResetKeep +# define inflateValidate z_inflateValidate # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # ifndef Z_SOLO # define uncompress z_uncompress +# define uncompress2 z_uncompress2 # endif # define zError z_zError # ifndef Z_SOLO @@ -226,9 +237,19 @@ # define z_const #endif -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ @@ -258,7 +279,7 @@ Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ @@ -463,8 +484,6 @@ typedef uLong FAR uLongf; #if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 # define Z_LFS64 -#else -# define _LFS64_LARGEFILE 0 #endif #if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) diff --git a/3rdparty/zlib/zlib.h b/3rdparty/zlib/zlib.h index 3e0c7672ac..f09cdaf1e0 100644 --- a/3rdparty/zlib/zlib.h +++ b/3rdparty/zlib/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.8, April 28th, 2013 + version 1.2.11, January 15th, 2017 - Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -37,11 +37,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.8" -#define ZLIB_VERNUM 0x1280 +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 8 +#define ZLIB_VER_REVISION 11 #define ZLIB_VER_SUBREVISION 0 /* @@ -65,7 +65,8 @@ extern "C" { with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - This library can optionally read and write gzip streams in memory as well. + This library can optionally read and write gzip and raw deflate streams in + memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- @@ -74,7 +75,7 @@ extern "C" { The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash - even in case of corrupted input. + even in the case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); @@ -87,7 +88,7 @@ typedef struct z_stream_s { uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total number of input bytes read so far */ - Bytef *next_out; /* next output byte should be put there */ + Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total number of bytes output so far */ @@ -98,8 +99,9 @@ typedef struct z_stream_s { free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; @@ -142,7 +144,9 @@ typedef gz_header FAR *gz_headerp; zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if @@ -155,7 +159,7 @@ typedef gz_header FAR *gz_headerp; The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use in the decompressor (particularly + uncompressed data and may be saved for use by the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ @@ -200,7 +204,7 @@ typedef gz_header FAR *gz_headerp; #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ +/* Possible values of the data_type field for deflate() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ @@ -258,11 +262,11 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - - Provide more output starting at next_out and update next_out and avail_out + - Generate more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). Some - output may be provided even if flush is not set. + should be set only when necessary. Some output may be provided even if + flush is zero. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more @@ -271,7 +275,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to @@ -292,8 +298,8 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed code - block. + in order for the decompressor to finish the block before the empty fixed + codes block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to @@ -319,34 +325,38 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the stream - are deflateReset or deflateEnd. + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). Then deflate is guaranteed to - return Z_STREAM_END. If not enough output space is provided, deflate will - not return Z_STREAM_END, and it must be called again as described above. + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect the - compression algorithm in any manner. + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. */ @@ -369,23 +379,21 @@ ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the - exact value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit() does not process any header information -- that is deferred - until inflate() is called. + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. */ @@ -401,17 +409,20 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing will - resume at this point for the next call of inflate(). + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). - - Provide more output starting at next_out and update next_out and avail_out + - Generate more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. The + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be @@ -428,7 +439,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the + To assist in this, on return inflate() always sets strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or @@ -454,7 +465,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all of the uncompressed data for the operation to complete. (The size of the uncompressed data may have been - saved by the compressor for this purpose.) The use of Z_FINISH is not + saved by the compressor for this purpose.) The use of Z_FINISH is not required to perform an inflation in one step. However it may be used to inform inflate that a faster approach can be used for the single inflate() call. Z_FINISH also informs inflate to not maintain a sliding window if the @@ -476,32 +487,33 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 + below. At the end of the stream, inflate() checks that its computed Adler-32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip - header is not retained, so applications that need that information should - instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. When processing + header is not retained unless inflateGetHeader() is used. When processing gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output - producted so far. The CRC-32 is checked against the gzip trailer. + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial - recovery of the data is desired. + recovery of the data is to be attempted. */ @@ -511,9 +523,8 @@ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); This function discards any unprocessed input and does not flush any pending output. - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. */ @@ -544,16 +555,29 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. + with no zlib header or trailer, and will not compute a check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is @@ -614,12 +638,12 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. - Upon return of this function, strm->adler is set to the adler32 value + Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value + which dictionary has been used by the compressor. (The Adler-32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. + Adler-32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is @@ -628,6 +652,28 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, not perform any compression: this will be done by deflate(). */ +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source)); /* @@ -648,10 +694,10 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. The - stream will keep the same compression level and any other attributes that - may have been set by deflateInit2. + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). @@ -662,20 +708,36 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int strategy)); /* Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be + interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. - If the compression level is changed, the input available so far is - compressed with the old level (and may be flushed); the new level will take - effect only at the next call of deflate(). + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to be - compressed and flushed. In particular, strm->avail_out must be non-zero. + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if - strm->avail_out was zero. + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. */ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, @@ -793,7 +855,7 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to + recommended that a check value such as an Adler-32 or a CRC-32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. @@ -802,7 +864,10 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - crc32 instead of an adler32. + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the @@ -823,7 +888,7 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. + can be determined from the Adler-32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called at any time to set the dictionary. If the provided dictionary is smaller than the @@ -834,7 +899,7 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not + expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ @@ -892,7 +957,7 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. The + but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source @@ -904,7 +969,9 @@ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if @@ -956,7 +1023,7 @@ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. - inflateMark returns the value noted above or -1 << 16 if the provided + inflateMark returns the value noted above, or -65536 if the provided source stream state was inconsistent. */ @@ -1048,9 +1115,9 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the normal - behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those @@ -1059,12 +1126,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). @@ -1092,7 +1159,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() + assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ @@ -1114,7 +1181,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); 7.6: size of z_off_t Compiler, assembler, and debug options: - 8: DEBUG + 8: ZLIB_DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) @@ -1164,7 +1231,8 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output @@ -1180,7 +1248,7 @@ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. + compressed data. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, @@ -1203,7 +1271,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed buffer. + is the actual size of the uncompressed data. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output @@ -1212,6 +1280,14 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, buffer with the uncompressed data up to that point. */ +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + /* gzip file access functions */ /* @@ -1290,10 +1366,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); default buffer size is 8192 bytes. This function must be called after gzopen() or gzdopen(), and before any other calls that read or write the file. The buffer memory allocation is always deferred to the first read or - write. Two buffers are allocated, either both of the specified size when - writing, or one of the specified size and the other twice that size when - reading. A larger buffer size of, for example, 64K or 128K bytes will - noticeably increase the speed of decompression (reading). + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). @@ -1304,10 +1379,12 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. */ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); @@ -1335,7 +1412,35 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); case. gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, @@ -1346,19 +1451,33 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, error. */ +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* Converts, formats, and writes the arguments to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or 0 in case of error. The number of - uncompressed bytes written is limited to 8191, or one less than the buffer - size given to gzbuffer(). The caller should assure that this limit is not - exceeded. If it is exceeded, then gzprintf() will return an error (0) with - nothing written. In this case, there may also be a buffer overflow with - unpredictable consequences, which is possible only if zlib was compiled with - the insecure functions sprintf() or vsprintf() because the secure snprintf() - or vsnprintf() functions were not available. This can be determined using - zlibCompileFlags(). + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). */ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); @@ -1418,7 +1537,7 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such - concatented gzip streams. + concatenated gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. @@ -1572,7 +1691,7 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); return the updated checksum. If buf is Z_NULL, this function returns the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed much faster. Usage example: @@ -1585,6 +1704,12 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (adler != original_adler) error(); */ +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + /* ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, z_off_t len2)); @@ -1614,6 +1739,12 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + /* ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); @@ -1644,19 +1775,35 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ - (int)sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, (int)sizeof(z_stream)) +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif #ifndef Z_SOLO @@ -1676,10 +1823,10 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef z_gzgetc # define z_gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #else # define gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or @@ -1737,19 +1884,16 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ #endif /* !Z_SOLO */ -/* hack for buggy compilers */ -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; -#endif - /* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); -#if defined(_WIN32) && !defined(Z_SOLO) +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, const char *mode)); #endif diff --git a/3rdparty/zlib/zutil.c b/3rdparty/zlib/zutil.c index 23d2ebef00..a76c6b0c7e 100644 --- a/3rdparty/zlib/zutil.c +++ b/3rdparty/zlib/zutil.c @@ -1,5 +1,5 @@ /* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. + * Copyright (C) 1995-2017 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -10,21 +10,18 @@ # include "gzguts.h" #endif -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - z_const char * const z_errmsg[10] = { -"need dictionary", /* Z_NEED_DICT 2 */ -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ -""}; + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; const char * ZEXPORT zlibVersion() @@ -61,7 +58,7 @@ uLong ZEXPORT zlibCompileFlags() case 8: flags += 2 << 6; break; default: flags += 3 << 6; } -#ifdef DEBUG +#ifdef ZLIB_DEBUG flags += 1 << 8; #endif #if defined(ASMV) || defined(ASMINF) @@ -115,8 +112,8 @@ uLong ZEXPORT zlibCompileFlags() return flags; } -#ifdef DEBUG - +#ifdef ZLIB_DEBUG +#include # ifndef verbose # define verbose 0 # endif @@ -219,9 +216,11 @@ local ptr_table table[MAX_PTR]; voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) { - voidpf buf = opaque; /* just to make some compilers happy */ + voidpf buf; ulg bsize = (ulg)items*size; + (void)opaque; + /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ @@ -244,6 +243,9 @@ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { int n; + + (void)opaque; + if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; @@ -259,7 +261,6 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) next_ptr--; return; } - ptr = opaque; /* just to make some compilers happy */ Assert(0, "zcfree: ptr not found"); } @@ -278,13 +279,13 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) { - if (opaque) opaque = 0; /* to make compiler happy */ + (void)opaque; return _halloc((long)items, size); } void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { - if (opaque) opaque = 0; /* to make compiler happy */ + (void)opaque; _hfree(ptr); } @@ -306,7 +307,7 @@ voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) unsigned items; unsigned size; { - if (opaque) items += size - size; /* make compiler happy */ + (void)opaque; return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } @@ -315,8 +316,8 @@ void ZLIB_INTERNAL zcfree (opaque, ptr) voidpf opaque; voidpf ptr; { + (void)opaque; free(ptr); - if (opaque) return; /* make compiler happy */ } #endif /* MY_ZCALLOC */ diff --git a/3rdparty/zlib/zutil.h b/3rdparty/zlib/zutil.h index 24ab06b1cf..b079ea6a80 100644 --- a/3rdparty/zlib/zutil.h +++ b/3rdparty/zlib/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -36,7 +36,9 @@ #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ typedef unsigned char uch; typedef uch FAR uchf; @@ -98,28 +100,38 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif #ifdef AMIGA -# define OS_CODE 0x01 +# define OS_CODE 1 #endif #if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 +# define OS_CODE 2 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif +#endif + #if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 +# define OS_CODE 5 #endif #ifdef OS2 -# define OS_CODE 0x06 +# define OS_CODE 6 # if defined(M_I86) && !defined(Z_SOLO) # include # endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 +# define OS_CODE 7 # ifndef Z_SOLO # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os # include /* for fdopen */ @@ -131,18 +143,24 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # endif #endif -#ifdef TOPS20 -# define OS_CODE 0x0a +#ifdef __acorn +# define OS_CODE 13 #endif -#ifdef WIN32 -# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ -# define OS_CODE 0x0b -# endif +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 #endif -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0f +#ifdef _BEOS_ +# define OS_CODE 16 +#endif + +#ifdef __TOS_OS400__ +# define OS_CODE 18 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 #endif #if defined(_BEOS_) || defined(RISCOS) @@ -177,7 +195,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* common defaults */ #ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ +# define OS_CODE 3 /* assume Unix */ #endif #ifndef F_OPEN @@ -216,7 +234,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif /* Diagnostic functions */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG # include extern int ZLIB_INTERNAL z_verbose; extern void ZLIB_INTERNAL z_error OF((char *m)); From d4e2e6279c65fdc0a213733dec68148b822a3023 Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Thu, 5 Oct 2017 20:36:38 +0300 Subject: [PATCH 2/8] 3rdparty: update libpng 1.6.34 --- 3rdparty/libpng/CHANGES | 370 +++++++++++++++++- 3rdparty/libpng/CMakeLists.txt | 4 +- 3rdparty/libpng/LICENSE | 9 +- 3rdparty/libpng/README | 19 +- 3rdparty/libpng/arm/filter_neon.S | 6 +- 3rdparty/libpng/contrib/intel/INSTALL | 158 -------- 3rdparty/libpng/contrib/intel/intel_sse.patch | 187 --------- .../intel/filter_sse2_intrinsics.c | 119 +++--- .../libpng/{contrib => }/intel/intel_init.c | 11 +- 3rdparty/libpng/opencv-libpng.patch | 105 ----- 3rdparty/libpng/png.c | 223 ++++++++--- 3rdparty/libpng/png.h | 80 ++-- 3rdparty/libpng/pngconf.h | 6 +- 3rdparty/libpng/pngerror.c | 10 +- 3rdparty/libpng/pngget.c | 35 +- 3rdparty/libpng/pnginfo.h | 8 + 3rdparty/libpng/pnglibconf.h | 11 +- 3rdparty/libpng/pngmem.c | 4 +- 3rdparty/libpng/pngpread.c | 12 +- 3rdparty/libpng/pngpriv.h | 355 +++++++++++------ 3rdparty/libpng/pngread.c | 101 +++-- 3rdparty/libpng/pngrtran.c | 64 +-- 3rdparty/libpng/pngrutil.c | 346 +++++++++++----- 3rdparty/libpng/pngset.c | 101 ++++- 3rdparty/libpng/pngstruct.h | 8 +- 3rdparty/libpng/pngtrans.c | 44 ++- 3rdparty/libpng/pngwrite.c | 77 ++-- 3rdparty/libpng/pngwtran.c | 4 +- 3rdparty/libpng/pngwutil.c | 83 ++-- 3rdparty/zlib/gzread.c | 6 +- 3rdparty/zlib/gzwrite.c | 6 +- 31 files changed, 1558 insertions(+), 1014 deletions(-) delete mode 100644 3rdparty/libpng/contrib/intel/INSTALL delete mode 100644 3rdparty/libpng/contrib/intel/intel_sse.patch rename 3rdparty/libpng/{contrib => }/intel/filter_sse2_intrinsics.c (84%) rename 3rdparty/libpng/{contrib => }/intel/intel_init.c (86%) delete mode 100644 3rdparty/libpng/opencv-libpng.patch diff --git a/3rdparty/libpng/CHANGES b/3rdparty/libpng/CHANGES index d4f0c8ba19..4b82118910 100644 --- a/3rdparty/libpng/CHANGES +++ b/3rdparty/libpng/CHANGES @@ -593,7 +593,7 @@ Version 1.0.5e [November 30, 1999] with trailing compressed parts easier in the future, and added new functions png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP, png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond). - NOTE: Applications that write text chunks MUST define png_text->lang + NOTE: Applications that write text chunks MUST define png_text->lang before calling png_set_text(). It must be set to NULL if you want to write tEXt or zTXt chunks. If you want your application to be able to run with older versions of libpng, use @@ -833,7 +833,7 @@ Version 1.0.7beta11 [May 7, 2000] Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes which are no longer used. Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is - defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED + defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXt_SUPPORTED is defined. Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory overrun when old applications fill the info_ptr->text structure directly. @@ -5675,6 +5675,372 @@ Version 1.6.24rc03 [August 2, 2016] Version 1.6.24[August 4, 2016] No changes. +Version 1.6.25beta01 [August 12, 2016] + Reject oversized iCCP profile immediately. + Cleaned up PNG_DEBUG compile of pngtest.c. + Conditionally compile png_inflate(). + +Version 1.6.25beta02 [August 18, 2016] + Don't install pngcp; it conflicts with pngcp in the pngtools package. + Minor editing of INSTALL, (whitespace, added copyright line) + +Version 1.6.25rc01 [August 24, 2016] + No changes. + +Version 1.6.25rc02 [August 29, 2016] + Added MIPS support (Mandar Sahastrabuddhe ). + Only the UP filter is currently implemented. + +Version 1.6.25rc03 [August 29, 2016] + Rebased contrib/intel/intel_sse.patch after the MIPS implementation. + +Version 1.6.25rc04 [August 30, 2016] + Added MIPS support for SUB, AVG, and PAETH filters (Mandar Sahastrabuddhe). + +Version 1.6.25rc05 [August 30, 2016] + Rebased contrib/intel/intel_sse.patch after the MIPS implementation update.. + +Version 1.6.25 [September 1, 2016] + No changes. + +Version 1.6.26beta01 [September 26, 2016] + Fixed handling zero length IDAT in pngfix (bug report by Agostino Sarubbo, + bugfix by John Bowler). + Do not issue a png_error() on read in png_set_pCAL() because png_handle_pCAL + has allocated memory that libpng needs to free. + Conditionally compile png_set_benign_errors() in pngread.c and pngtest.c + Issue a png_benign_error instead of a png_error on ADLER32 mismatch + while decoding compressed data chunks. + Changed PNG_ZLIB_VERNUM to ZLIB_VERNUM in pngpriv.h, pngstruct.h, and + pngrutil.c. + If CRC handling of critical chunks has been set to PNG_CRC_QUIET_USE, + ignore the ADLER32 checksum in the IDAT chunk as well as the chunk CRCs. + Issue png_benign_error() on ADLER32 checksum mismatch instead of png_error(). + Add tests/badcrc.png and tests/badadler.png to tests/pngtest. + Merged pngtest.c with libpng-1.7.0beta84/pngtest.c + +Version 1.6.26beta02 [October 1, 2016] + Updated the documentation about CRC and ADLER32 handling. + Quieted 117 warnings from clang-3.8 in pngtrans.c, pngread.c, + pngwrite.c, pngunknown.c, and pngvalid.c. + Quieted 58 (out of 144) -Wconversion compiler warnings by changing + flag definitions in pngpriv.h from 0xnnnn to 0xnnnnU and trivial changes + in png.c, pngread.c, and pngwutil.c. + +Version 1.6.26beta03 [October 2, 2016] + Removed contrib/libtests/*.orig and *.rej that slipped into the tarballs. + Quieted the 86 remaining -Wconversion compiler warnings by + revising the png_isaligned() macro and trivial changes in png.c, + pngerror.c, pngget.c, pngmem.c, pngset.c, pngrtran.c, pngrutil.c, + pngwtran.c, pngwrite.c, and pngwutil.c. + +Version 1.6.26beta04 [October 3, 2016] + Quieted (bogus?) clang warnings about "absolute value has no effect" + when PNG_USE_ABS is defined. + Fixed offsets in contrib/intel/intel_sse.patch + +Version 1.6.26beta05 [October 6, 2016] + Changed integer constant 4294967294 to unsigned 4294967294U in pngconf.h + to avoid a signed/unsigned compare in the preprocessor. + +Version 1.6.26beta06 [October 7, 2016] + Use zlib-1.2.8.1 inflateValidate() instead of inflateReset2() to + optionally avoid ADLER32 evaluation. + +Version 1.6.26rc01 [October 12, 2016] + No changes. + +Version 1.6.26 [October 20, 2016] + Cosmetic change, "ptr != 0" to "ptr != NULL" in png.c and pngrutil.c + Despammed email addresses (replaced "@" with " at "). + +Version 1.6.27beta01 [November 2, 2016] + Restrict the new ADLER32-skipping to IDAT chunks. It broke iCCP chunk + handling: an erroneous iCCP chunk would throw a png_error and reject the + entire PNG image instead of rejecting just the iCCP chunk with a warning, + if built with zlib-1.2.8.1. + +Version 1.6.27rc01 [December 27, 2016] + Control ADLER32 checking with new PNG_IGNORE_ADLER32 option. Fixes + an endless loop when handling erroneous ADLER32 checksums; bug + introduced in libpng-1.6.26. + Removed the use of a macro containing the pre-processor 'defined' + operator. It is unclear whether this is valid; a macro that + "generates" 'defined' is not permitted, but the use of the word + "generates" within the C90 standard seems to imply more than simple + substitution of an expression itself containing a well-formed defined + operation. + Added ARM support to CMakeLists.txt (Andreas Franek). + +Version 1.6.27 [December 29, 2016] + Fixed a potential null pointer dereference in png_set_text_2() (bug report + and patch by Patrick Keshishian, CVE-2016-10087). + +Version 1.6.28rc01 [January 3, 2017] + Fixed arm/aarch64 detection in CMakeLists.txt (Gianfranco Costamagna). + Added option to Cmake build allowing a custom location of zlib to be + specified in a scenario where libpng is being built as a subproject + alongside zlib by another project (Sam Serrels). + Changed png_ptr->options from a png_byte to png_uint_32, to accomodate + up to 16 options. + +Version 1.6.28rc02 [January 4, 2017] + Added "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna). + Moved SSE2 optimization code into the main libpng source directory. + Configure libpng with "configure --enable-intel-sse" or compile + libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it. + +Version 1.6.28rc03 [January 4, 2017] + Backed out the SSE optimization and last CMakeLists.txt to allow time for QA. + +Version 1.6.28 [January 5, 2017] + No changes. + +Version 1.6.29beta01 [January 12, 2017] + Readded "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna). + Moved SSE2 optimization code into the main libpng source directory. + Configure libpng with "configure --enable-intel-sse" or compile + libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it. + Simplified conditional compilation in pngvalid.c, for AIX (Michael Felt). + +Version 1.6.29beta02 [February 22, 2017] + Avoid conditional directives that break statements in pngrutil.c (Romero + Malaquias) + The contrib/examples/pngtopng.c recovery code was in the wrong "if" + branches; the comments were correct. + Added code for PowerPC VSX optimisation (Vadim Barkov). + +Version 1.6.29beta03 [March 1, 2017] + Avoid potential overflow of shift operations in png_do_expand() (Aaron Boxer). + Change test ZLIB_VERNUM >= 0x1281 to ZLIB_VERNUM >= 0x1290 in pngrutil.c + because Solaris 11 distributes zlib-1.2.8.f that is older than 1.2.8.1, + as suggested in zlib FAQ, item 24. + Suppress clang warnings about implicit sign changes in png.c + +Version 1.6.29 [March 16, 2017] + No changes. + +Version 1.6.30beta01 [April 1, 2017] + Added missing "$(CPPFLAGS)" to the compile line for c.pic.o in + makefile.linux and makefile.solaris-x86 (Cosmin). + Revised documentation of png_get_error_ptr() in the libpng manual. + Silence clang -Wcomma and const drop warnings (Viktor Szakats). + Update Sourceforge URLs in documentation (https instead of http). + +Version 1.6.30beta02 [April 22, 2017] + Document need to check for integer overflow when allocating a pixel + buffer for multiple rows in contrib/gregbook, contrib/pngminus, + example.c, and in the manual (suggested by Jaeseung Choi). This + is similar to the bug reported against pngquant in CVE-2016-5735. + Removed reference to the obsolete PNG_SAFE_LIMITS macro in the documentation. + +Version 1.6.30beta03 [May 22, 2017] + Check for integer overflow in contrib/visupng and contrib/tools/genpng. + Do not double evaluate CMAKE_SYSTEM_PROCESSOR in CMakeLists.txt. + Test CMAKE_HOST_WIN32 instead of WIN32 in CMakeLists.txt. + Fix some URL in documentation. + +Version 1.6.30beta04 [June 7, 2017] + Avoid writing an empty IDAT when the last IDAT exactly fills the + compression buffer (bug report by Brian Baird). This bug was + introduced in libpng-1.6.0. + +Version 1.6.30rc01 [June 14, 2017] + No changes. + +Version 1.6.30rc02 [June 25, 2017] + Update copyright year in pnglibconf.h, make ltmain.sh executable. + Add a reference to the libpng.download site in README. + +Version 1.6.30 [June 28, 2017] + No changes. + +Version 1.6.31beta01 [July 5, 2017] + Guard the definition of _POSIX_SOURCE in pngpriv.h (AIX already defines it; + bug report by Michael Felt). + Revised pngpriv.h to work around failure to compile arm/filter_neon.S + ("typedef" directive is unrecognized by the assembler). The problem + was introduced in libpng-1.6.30beta01. + Added "Requires: zlib" to libpng.pc.in (Pieter Neerincx). + Added special case for FreeBSD in arm/filter_neon.S (Maya Rashish). + +Version 1.6.31beta02 [July 8, 2017] + Added instructions for disabling hardware optimizations in INSTALL. + Added "--enable-hardware-optimizations" configuration flag to enable + or disable all hardware optimizations with one flag. + +Version 1.6.31beta03 [July 9, 2017] + Updated CMakeLists.txt to add INTEL_SSE and MIPS_MSA platforms. + Changed "int" to "png_size_t" in intel/filter_sse2.c to prevent + possible integer overflow (Bug report by John Bowler). + Quieted "declaration after statement" warnings in intel/filter_sse2.c. + Added scripts/makefile-linux-opt, which has hardware optimizations enabled. + +Version 1.6.31beta04 [July 11, 2017] + Removed one of the GCC-7.1.0 'strict-overflow' warnings that result when + integers appear on both sides of a compare. Worked around the others by + forcing the strict-overflow setting in the relevant functions to a level + where they are not reported (John Bowler). + Changed "FALL THROUGH" comments to "FALLTHROUGH" because GCC doesn't like + the space. + Worked around some C-style casts from (void*) because g++ 5.4.0 objects + to them. + Increased the buffer size for 'sprint' to pass the gcc 7.1.0 'sprint + overflow' check that is on by default with -Wall -Wextra. + +Version 1.6.31beta05 [July 13, 2017] + Added eXIf chunk support. + +Version 1.6.31beta06 [July 17, 2017] + Added a minimal eXIf chunk (with Orientation and FocalLengthIn35mmFilm + tags) to pngtest.png. + +Version 1.6.31beta07 [July 18, 2017] + Revised the eXIf chunk in pngtest.png to fix "Bad IFD1 Directory" warning. + +Version 1.6.31rc01 [July 19, 2017] + No changes. + +Version 1.6.31rc02 [July 25, 2017] + Fixed typo in example.c (png_free_image should be png_image_free) (Bug + report by John Smith) + +Version 1.6.31 [July 27, 2017] + No changes. + +Version 1.6.32beta01 [July 31, 2017] + Avoid possible NULL dereference in png_handle_eXIf when benign_errors + are allowed. Avoid leaking the input buffer "eXIf_buf". + Eliminated png_ptr->num_exif member from pngstruct.h and added num_exif + to arguments for png_get_eXIf() and png_set_eXIf(). + Added calls to png_handle_eXIf(() in pngread.c and png_write_eXIf() in + pngwrite.c, and made various other fixes to png_write_eXIf(). + Changed name of png_get_eXIF and png_set_eXIf() to png_get_eXIf_1() and + png_set_eXIf_1(), respectively, to avoid breaking API compatibility + with libpng-1.6.31. + +Version 1.6.32beta02 [August 1, 2017] + Updated contrib/libtests/pngunknown.c with eXIf chunk. + +Version 1.6.32beta03 [August 2, 2017] + Initialized btoa[] in pngstest.c + Stop memory leak when returning from png_handle_eXIf() with an error + (Bug report from the OSS-fuzz project). + +Version 1.6.32beta04 [August 2, 2017] + Replaced local eXIf_buf with info_ptr-eXIf_buf in png_handle_eXIf(). + Update libpng.3 and libpng-manual.txt about eXIf functions. + +Version 1.6.32beta05 [August 2, 2017] + Restored png_get_eXIf() and png_set_eXIf() to maintain API compatability. + +Version 1.6.32beta06 [August 2, 2017] + Removed png_get_eXIf_1() and png_set_eXIf_1(). + +Version 1.6.32beta07 [August 3, 2017] + Check length of all chunks except IDAT against user limit to fix an + OSS-fuzz issue (Fixes CVE-2017-12652). + +Version 1.6.32beta08 [August 3, 2017] + Check length of IDAT against maximum possible IDAT size, accounting + for height, rowbytes, interlacing and zlib/deflate overhead. + Restored png_get_eXIf_1() and png_set_eXIf_1(), because strlen(eXIf_buf) + does not work (the eXIf chunk data can contain zeroes). + +Version 1.6.32beta09 [August 3, 2017] + Require cmake-2.8.8 in CMakeLists.txt. Revised symlink creation, + no longer using deprecated cmake LOCATION feature (Clifford Yapp). + Fixed five-byte error in the calculation of IDAT maximum possible size. + +Version 1.6.32beta10 [August 5, 2017] + Moved chunk-length check into a png_check_chunk_length() private + function (Suggested by Max Stepin). + Moved bad pngs from tests to contrib/libtests/crashers + Moved testing of bad pngs into a separate tests/pngtest-badpngs script + Added the --xfail (expected FAIL) option to pngtest.c. It writes XFAIL + in the output but PASS for the libpng test. + Require cmake-3.0.2 in CMakeLists.txt (Clifford Yapp). + Fix "const" declaration info_ptr argument to png_get_eXIf_1() and the + num_exif argument to png_get_eXIf_1() (Github Issue 171). + +Version 1.6.32beta11 [August 7, 2017] + Added "eXIf" to "chunks_to_ignore[]" in png_set_keep_unknown_chunks(). + Added huge_IDAT.png and empty_ancillary_chunks.png to testpngs/crashers. + Make pngtest --strict, --relax, --xfail options imply -m (multiple). + Removed unused chunk_name parameter from png_check_chunk_length(). + Relocated setting free_me for eXIf data, to stop an OSS-fuzz leak. + Initialize profile_header[] in png_handle_iCCP() to fix OSS-fuzz issue. + Initialize png_ptr->row_buf[0] to 255 in png_read_row() to fix OSS-fuzz UMR. + Attempt to fix a UMR in png_set_text_2() to fix OSS-fuzz issue. + Increase minimum zlib stream from 9 to 14 in png_handle_iCCP(), to account + for the minimum 'deflate' stream, and relocate the test to a point + after the keyword has been read. + Check that the eXIf chunk has at least 2 bytes and begins with "II" or "MM". + +Version 1.6.32rc01 [August 18, 2017] + Added a set of "huge_xxxx_chunk.png" files to contrib/testpngs/crashers, + one for each known chunk type, with length = 2GB-1. + Check for 0 return from png_get_rowbytes() and added some (size_t) typecasts + in contrib/pngminus/*.c to stop some Coverity issues (162705, 162706, + and 162707). + Renamed chunks in contrib/testpngs/crashers to avoid having files whose + names differ only in case; this causes problems with some platforms + (github issue #172). + +Version 1.6.32rc02 [August 22, 2017] + Added contrib/oss-fuzz directory which contains files used by the oss-fuzz + project (https://github.com/google/oss-fuzz/tree/master/projects/libpng). + +Version 1.6.32 [August 24, 2017] + No changes. + +Version 1.6.33beta01 [August 28, 2017] + Added PNGMINUS_UNUSED macro to contrib/pngminus/p*.c and added missing + parenthesis in contrib/pngminus/pnm2png.c (bug report by Christian Hesse). + Fixed off-by-one error in png_do_check_palette_indexes() (Bug report + by Mick P., Source Forge Issue #269). + +Version 1.6.33beta02 [September 3, 2017] + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + to fix shortlived oss-fuzz issue 3234. + Compute a larger limit on IDAT because some applications write a deflate + buffer for each row (Bug report by Andrew Church). + Use current date (DATE) instead of release-date (RDATE) in last + changed date of contrib/oss-fuzz files. + Enabled ARM support in CMakeLists.txt (Bernd Kuhls). + +Version 1.6.33beta03 [September 14, 2017] + Fixed incorrect typecast of some arguments to png_malloc() and + png_calloc() that were png_uint_32 instead of png_alloc_size_t + (Bug report by "irwir" in Github libpng issue #175). + Use pnglibconf.h.prebuilt when building for ANDROID with cmake (Github + issue 162, by rcdailey). + +Version 1.6.33rc01 [September 20, 2017] + Initialize memory allocated by png_inflate to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in png_set_text_2() + due to truncated iTXt or zTXt chunk. + Initialize memory allocated by png_read_buffer to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in + png_icc_check_tag_table() due to truncated iCCP chunk. + Removed a redundant test (suggested by "irwir" in Github issue #180). + +Version 1.6.33rc02 [September 23, 2017] + Added an interlaced version of each file in contrib/pngsuite. + Relocate new memset() call in pngrutil.c. + Removed more redundant tests (suggested by "irwir" in Github issue #180). + Add support for loading images with associated alpha in the Simplified + API (Samuel Williams). + +Version 1.6.33 [September 28, 2017] + Revert contrib/oss-fuzz/libpng_read_fuzzer.cc to libpng-1.6.32 state. + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + Add end_info structure and png_read_end() to the libpng fuzzer. + +Version 1.6.34 [September 29, 2017] + Removed contrib/pngsuite/i*.png; some of these were incorrect and caused + test failures. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt index 8d338e7636..92f7447985 100644 --- a/3rdparty/libpng/CMakeLists.txt +++ b/3rdparty/libpng/CMakeLists.txt @@ -37,9 +37,9 @@ if(ARM OR AARCH64) endif() endif() -if(ENABLE_SSE +if(";${CPU_BASELINE_FINAL};" MATCHES "SSE2" AND (NOT MSVC OR (MSVC_VERSION GREATER 1799))) # MSVS2013+ (issue #7232) - list(APPEND lib_srcs contrib/intel/intel_init.c contrib/intel/filter_sse2_intrinsics.c) + list(APPEND lib_srcs intel/intel_init.c intel/filter_sse2_intrinsics.c) add_definitions(-DPNG_INTEL_SSE) endif() diff --git a/3rdparty/libpng/LICENSE b/3rdparty/libpng/LICENSE index d20f39e2b9..4cda4fa0ad 100644 --- a/3rdparty/libpng/LICENSE +++ b/3rdparty/libpng/LICENSE @@ -10,8 +10,8 @@ this sentence. This code is released under the libpng license. -libpng versions 1.0.7, July 1, 2000 through 1.6.24, August 4, 2016 are -Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are +libpng versions 1.0.7, July 1, 2000 through 1.6.34, September 29, 2017 are +Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are derived from libpng-1.0.6, and are distributed according to the same disclaimer and license as libpng-1.0.6 with the following individuals added to the list of Contributing Authors: @@ -22,6 +22,9 @@ added to the list of Contributing Authors: Cosmin Truta Gilles Vollant James Yu + Mandar Sahastrabuddhe + Google Inc. + Vadim Barkov and with the following additions to the disclaimer: @@ -127,4 +130,4 @@ any encryption software. See the EAR, paragraphs 734.3(b)(3) and Glenn Randers-Pehrson glennrp at users.sourceforge.net -August 4, 2016 +September 29, 2017 diff --git a/3rdparty/libpng/README b/3rdparty/libpng/README index a8fba9168b..0da5a5ef83 100644 --- a/3rdparty/libpng/README +++ b/3rdparty/libpng/README @@ -1,4 +1,4 @@ -README for libpng version 1.6.24 - August 4, 2016 (shared library 16.0) +README for libpng version 1.6.34 - September 29, 2017 (shared library 16.0) See the note about version numbers near the top of png.h See INSTALL for instructions on how to install libpng. @@ -23,7 +23,7 @@ earlier versions if you are using a shared library. The type of the png_uint_32, which will affect shared-library applications that use this function. -To avoid problems with changes to the internals of png info_struct, +To avoid problems with changes to the internals of the png info_struct, new APIs have been made available in 0.95 to avoid direct application access to info_ptr. These functions are the png_set_ and png_get_ functions. These functions should be used when @@ -88,11 +88,11 @@ zlib should be available at the same place that libpng is, or at zlib.net. You may also want a copy of the PNG specification. It is available as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find -these at http://www.libpng.org/pub/png/documents/ +these at http://www.libpng.org/pub/png/pngdocs.html . -This code is currently being archived at libpng.sf.net in the -[DOWNLOAD] area, and at ftp://ftp.simplesystems.org. If you can't find it -in any of those places, e-mail me, and I'll help you find it. +This code is currently being archived at libpng.sourceforge.io in the +[DOWNLOAD] area, and at http://libpng.download/src . If you +can't find it in any of those places, e-mail me, and I'll help you find it. I am not a lawyer, but I believe that the Export Control Classification Number (ECCN) for libpng is EAR99, which means not subject to export @@ -179,18 +179,25 @@ Files in this distribution: pngwtran.c => Write data transformations pngwutil.c => Write utility functions arm => Contains optimized code for the ARM platform + powerpc => Contains optimized code for the PowerPC platform contrib => Contributions + arm-neon => Optimized code for ARM-NEON platform + powerpc-vsx => Optimized code for POWERPC-VSX platform examples => Example programs gregbook => source code for PNG reading and writing, from Greg Roelofs' "PNG: The Definitive Guide", O'Reilly, 1999 libtests => Test programs + mips-msa => Optimized code for MIPS-MSA platform pngminim => Minimal decoder, encoder, and progressive decoder programs demonstrating use of pngusr.dfa pngminus => Simple pnm2png and png2pnm programs pngsuite => Test images + testpngs tools => Various tools visupng => Contains a MSVC workspace for VisualPng + intel => Optimized code for INTEL-SSE2 platform + mips => Optimized code for MIPS platform projects => Contains project files and workspaces for building a DLL owatcom => Contains a WATCOM project for building libpng diff --git a/3rdparty/libpng/arm/filter_neon.S b/3rdparty/libpng/arm/filter_neon.S index 3b061d6bbf..000764cd21 100644 --- a/3rdparty/libpng/arm/filter_neon.S +++ b/3rdparty/libpng/arm/filter_neon.S @@ -1,9 +1,9 @@ /* filter_neon.S - NEON optimised filter functions * - * Copyright (c) 2014 Glenn Randers-Pehrson + * Copyright (c) 2014,2017 Glenn Randers-Pehrson * Written by Mans Rullgard, 2011. - * Last changed in libpng 1.6.16 [December 22, 2014] + * Last changed in libpng 1.6.31 [July 27, 2017] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -16,7 +16,7 @@ #define PNG_VERSION_INFO_ONLY #include "../pngpriv.h" -#if defined(__linux__) && defined(__ELF__) +#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__) .section .note.GNU-stack,"",%progbits /* mark stack as non-executable */ #endif diff --git a/3rdparty/libpng/contrib/intel/INSTALL b/3rdparty/libpng/contrib/intel/INSTALL deleted file mode 100644 index cd5cdd94eb..0000000000 --- a/3rdparty/libpng/contrib/intel/INSTALL +++ /dev/null @@ -1,158 +0,0 @@ -Enabling SSE support - -Copyright (c) 2016 Google, Inc. -Written by Mike Klein, Matt Sarett - -This INSTALL file written by Glenn Randers-Pehrson, 2016. - -If you have moved intel_init.c and filter_sse2_intrinsics.c to a different -directory, be sure to update the '#include "../../pngpriv.h"' line in both -files if necessary to point to the correct relative location of pngpriv.h -with respect to the new location of those files. - -To enable SSE support in libpng, follow the instructions in I, II, or III, -below: - -I. Using patched "configure" scripts: - -First, apply intel_sse.patch in your build directory. - - patch -i contrib/intel/intel_sse.patch -p1 - -Then, if you are not building in a new GIT clone, e.g., in a tar -distribution, remove any existing pre-built configure scripts: - - ./configure --enable-maintainer-mode - make maintainer-clean - ./autogen.sh --maintainer --clean - -Finally, configure libpng with -DPNG_INTEL_SSE in CPPFLAGS: - - ./autogen.sh --maintainer - CPPFLAGS="-DPNG_INTEL_SSE" ./configure [options] - make CPPFLAGS="-DPNG_INTEL_SSE" [options] - make - -II. Using a custom makefile: - -If you are using a custom makefile makefile, you will have to update it -manually to include contrib/intel/*.o in the dependencies, and to define -PNG_INTEL_SSE. - -III. Using manually updated "configure" scripts: - -If you prefer, manually edit pngpriv.h, configure.ac, and Makefile.am, -following the instructions below, then follow the instructions in -section II of INSTALL in the main libpng directory, then configure libpng -with -DPNG_INTEL_SSE in CPPFLAGS. - -1. Add the following code to configure.ac under HOST SPECIFIC OPTIONS -directly beneath the section for ARM: - ------------------cut---------------- -# INTEL -# ===== -# -# INTEL SSE (SIMD) support. - -AC_ARG_ENABLE([intel-sse], - AS_HELP_STRING([[[--enable-intel-sse]]], - [Enable Intel SSE optimizations: =no/off, yes/on:] - [no/off: disable the optimizations;] - [yes/on: enable the optimizations.] - [If not specified: determined by the compiler.]), - [case "$enableval" in - no|off) - # disable the default enabling: - AC_DEFINE([PNG_INTEL_SSE_OPT], [0], - [Disable Intel SSE optimizations]) - # Prevent inclusion of the assembler files below: - enable_intel_sse=no;; - yes|on) - AC_DEFINE([PNG_INTEL_SSE_OPT], [1], - [Enable Intel SSE optimizations]);; - *) - AC_MSG_ERROR([--enable-intel-sse=${enable_intel_sse}: invalid value]) - esac]) - -# Add Intel specific files to all builds where the host_cpu is Intel ('x86*') -# or where Intel optimizations were explicitly requested (this allows a -# fallback if a future host CPU does not match 'x86*') -AM_CONDITIONAL([PNG_INTEL_SSE], - [test "$enable_intel_sse" != 'no' && - case "$host_cpu" in - i?86|x86_64) :;; - *) test "$enable_intel_sse" != '';; - esac]) ------------------cut---------------- - -2. Add the following code to Makefile.am under HOST SPECIFIC OPTIONS -directly beneath the "if PNG_ARM_NEON ... endif" statement: - ------------------cut---------------- -if PNG_INTEL_SSE -libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += contrib/intel/intel_init.c\ - contrib/intel/filter_sse2_intrinsics.c -endif ------------------cut---------------- - -3. Add the following lines to pngpriv.h, following the PNG_ARM_NEON_OPT -code: - ------------------cut---------------- -#ifndef PNG_INTEL_SSE_OPT -# ifdef PNG_INTEL_SSE - /* Only check for SSE if the build configuration has been modified to - * enable SSE optimizations. This means that these optimizations will - * be off by default. See contrib/intel for more details. - */ -# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ - defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ - (defined(_M_IX86_FP) && _M_IX86_FP >= 2) -# define PNG_INTEL_SSE_OPT 1 -# endif -# endif -#endif - -#if PNG_INTEL_SSE_OPT > 0 -# ifndef PNG_INTEL_SSE_IMPLEMENTATION -# if defined(__SSE4_1__) || defined(__AVX__) - /* We are not actually using AVX, but checking for AVX is the best - way we can detect SSE4.1 and SSSE3 on MSVC. - */ -# define PNG_INTEL_SSE_IMPLEMENTATION 3 -# elif defined(__SSSE3__) -# define PNG_INTEL_SSE_IMPLEMENTATION 2 -# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ - (defined(_M_IX86_FP) && _M_IX86_FP >= 2) -# define PNG_INTEL_SSE_IMPLEMENTATION 1 -# else -# define PNG_INTEL_SSE_IMPLEMENTATION 0 -# endif -# endif - -# if PNG_INTEL_SSE_IMPLEMENTATION > 0 -# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 -# endif -#endif - ------------------cut---------------- - -4. Add the following lines to pngpriv.h, following the prototype for -png_read_filter_row_paeth4_neon: - ------------------cut---------------- -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); - ------------------cut---------------- diff --git a/3rdparty/libpng/contrib/intel/intel_sse.patch b/3rdparty/libpng/contrib/intel/intel_sse.patch deleted file mode 100644 index c5579e3abd..0000000000 --- a/3rdparty/libpng/contrib/intel/intel_sse.patch +++ /dev/null @@ -1,187 +0,0 @@ -diff --git a/configure.ac b/configure.ac ---- a/configure.ac 2016-05-25 18:59:10.000000000 -0400 -+++ b/configure.ac 2016-05-25 19:48:10.631751170 -0400 -@@ -341,16 +341,50 @@ AC_ARG_ENABLE([arm-neon], - - AM_CONDITIONAL([PNG_ARM_NEON], - [test "$enable_arm_neon" != 'no' && - case "$host_cpu" in - arm*|aarch64*) :;; - *) test "$enable_arm_neon" != '';; - esac]) - -+# INTEL -+# ===== -+# -+# INTEL SSE (SIMD) support. -+ -+AC_ARG_ENABLE([intel-sse], -+ AS_HELP_STRING([[[--enable-intel-sse]]], -+ [Enable Intel SSE optimizations: =no/off, yes/on:] -+ [no/off: disable the optimizations;] -+ [yes/on: enable the optimizations.] -+ [If not specified: determined by the compiler.]), -+ [case "$enableval" in -+ no|off) -+ # disable the default enabling: -+ AC_DEFINE([PNG_INTEL_SSE_OPT], [0], -+ [Disable Intel SSE optimizations]) -+ # Prevent inclusion of the assembler files below: -+ enable_intel_sse=no;; -+ yes|on) -+ AC_DEFINE([PNG_INTEL_SSE_OPT], [1], -+ [Enable Intel SSE optimizations]);; -+ *) -+ AC_MSG_ERROR([--enable-intel-sse=${enable_intel_sse}: invalid value]) -+ esac]) -+ -+# Add Intel specific files to all builds where the host_cpu is Intel ('x86*') -+# or where Intel optimizations were explicitly requested (this allows a -+# fallback if a future host CPU does not match 'x86*') -+AM_CONDITIONAL([PNG_INTEL_SSE], -+ [test "$enable_intel_sse" != 'no' && -+ case "$host_cpu" in -+ i?86|x86_64) :;; -+ *) test "$enable_intel_sse" != '';; -+ esac]) - AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]]) - - # Config files, substituting as above - AC_CONFIG_FILES([Makefile libpng.pc:libpng.pc.in]) - AC_CONFIG_FILES([libpng-config:libpng-config.in], - [chmod +x libpng-config]) - - AC_OUTPUT -diff --git a/Makefile.am b/Makefile.am ---- a/Makefile.am 2016-05-17 18:15:12.000000000 -0400 -+++ b/Makefile.am 2016-05-25 19:48:10.631751170 -0400 -@@ -92,16 +92,20 @@ libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SO - pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\ - png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h pngusr.dfa - - if PNG_ARM_NEON - libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += arm/arm_init.c\ - arm/filter_neon.S arm/filter_neon_intrinsics.c - endif - -+if PNG_INTEL_SSE -+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += contrib/intel/intel_init.c\ -+ contrib/intel/filter_sse2_intrinsics.c -+endif - nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h - - libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined -export-dynamic \ - -version-number @PNGLIB_MAJOR@@PNGLIB_MINOR@:@PNGLIB_RELEASE@:0 - - if HAVE_LD_VERSION_SCRIPT - # Versioned symbols and restricted exports - if HAVE_SOLARIS_LD -diff --git a/pngpriv.h b/pngpriv.h ---- a/pngpriv.h 2016-08-01 18:13:38.770128810 -0500 -+++ b/pngpriv.h 2016-08-01 18:50:19.130179017 -0500 -@@ -177,16 +177,52 @@ - # endif /* !PNG_ARM_NEON_IMPLEMENTATION */ - - # ifndef PNG_ARM_NEON_IMPLEMENTATION - /* Use the intrinsics code by default. */ - # define PNG_ARM_NEON_IMPLEMENTATION 1 - # endif - #endif /* PNG_ARM_NEON_OPT > 0 */ - -+#ifndef PNG_INTEL_SSE_OPT -+# ifdef PNG_INTEL_SSE -+ /* Only check for SSE if the build configuration has been modified to -+ * enable SSE optimizations. This means that these optimizations will -+ * be off by default. See contrib/intel for more details. -+ */ -+# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ -+ defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ -+ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) -+# define PNG_INTEL_SSE_OPT 1 -+# endif -+# endif -+#endif -+ -+#if PNG_INTEL_SSE_OPT > 0 -+# ifndef PNG_INTEL_SSE_IMPLEMENTATION -+# if defined(__SSE4_1__) || defined(__AVX__) -+ /* We are not actually using AVX, but checking for AVX is the best -+ way we can detect SSE4.1 and SSSE3 on MSVC. -+ */ -+# define PNG_INTEL_SSE_IMPLEMENTATION 3 -+# elif defined(__SSSE3__) -+# define PNG_INTEL_SSE_IMPLEMENTATION 2 -+# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ -+ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) -+# define PNG_INTEL_SSE_IMPLEMENTATION 1 -+# else -+# define PNG_INTEL_SSE_IMPLEMENTATION 0 -+# endif -+# endif -+ -+# if PNG_INTEL_SSE_IMPLEMENTATION > 0 -+# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 -+# endif -+#endif -+ - /* Is this a build of a DLL where compilation of the object modules requires - * different preprocessor settings to those required for a simple library? If - * so PNG_BUILD_DLL must be set. - * - * If libpng is used inside a DLL but that DLL does not export the libpng APIs - * PNG_BUILD_DLL must not be set. To avoid the code below kicking in build a - * static library of libpng then link the DLL against that. - */ -@@ -1185,16 +1221,31 @@ PNG_INTERNAL_FUNCTION(void,png_read_filt - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); - PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); - PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); - PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); - #endif -+ -+#if PNG_INTEL_SSE_IMPLEMENTATION > 0 -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+#endif - - /* Choose the best filter to use and filter the row data */ - PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, - png_row_infop row_info),PNG_EMPTY); - - #ifdef PNG_SEQUENTIAL_READ_SUPPORTED - PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr, - png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY); -@@ -1914,16 +1965,20 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_O - /* List *all* the possible optimizations here - this branch is required if - * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in - * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing. - */ - # if PNG_ARM_NEON_OPT > 0 - PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, - (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); - # endif -+# if PNG_INTEL_SSE_IMPLEMENTATION > 0 -+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, -+ (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); -+# endif - #endif - - PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, - png_const_charp key, png_bytep new_key), PNG_EMPTY); - - /* Maintainer: Put new private prototypes here ^ */ - - #include "pngdebug.h" diff --git a/3rdparty/libpng/contrib/intel/filter_sse2_intrinsics.c b/3rdparty/libpng/intel/filter_sse2_intrinsics.c similarity index 84% rename from 3rdparty/libpng/contrib/intel/filter_sse2_intrinsics.c rename to 3rdparty/libpng/intel/filter_sse2_intrinsics.c index 2bde138719..5e8553fbb9 100644 --- a/3rdparty/libpng/contrib/intel/filter_sse2_intrinsics.c +++ b/3rdparty/libpng/intel/filter_sse2_intrinsics.c @@ -1,19 +1,18 @@ /* filter_sse2_intrinsics.c - SSE2 optimized filter functions * - * Copyright (c) 2016 Google, Inc. + * Copyright (c) 2016-2017 Glenn Randers-Pehrson * Written by Mike Klein and Matt Sarett - * Derived from arm/filter_neon_intrinsics.c, which was - * Copyright (c) 2014,2016 Glenn Randers-Pehrson + * Derived from arm/filter_neon_intrinsics.c * - * Last changed in libpng 1.6.24 [August 4, 2016] + * Last changed in libpng 1.6.31 [July 27, 2017] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ -#include "../../pngpriv.h" +#include "../pngpriv.h" #ifdef PNG_READ_SUPPORTED @@ -41,7 +40,7 @@ static __m128i load3(const void* p) { /* We'll load 2 bytes, then 1 byte, * then mask them together, and finally load into SSE. */ - const png_uint_16* p01 = p; + const png_uint_16* p01 = (png_const_uint_16p)p; const png_byte* p2 = (const png_byte*)(p01+1); png_uint_32 v012 = (png_uint_32)(*p01) @@ -54,12 +53,15 @@ static void store3(void* p, __m128i v) { * its bottom two bytes, then its third byte. */ png_uint_32 v012; + png_uint_16* p01; + png_byte* p2; + store4(&v012, v); - png_uint_16* p01 = p; - png_byte* p2 = (png_byte*)(p01+1); - *p01 = v012; - *p2 = v012 >> 16; + p01 = (png_uint_16p)p; + p2 = (png_byte*)(p01+1); + *p01 = (png_uint_16)v012; + *p2 = (png_byte)(v012 >> 16); } void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row, @@ -69,11 +71,13 @@ void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row, * There is no pixel to the left of the first pixel. It's encoded directly. * That works with our main loop if we just say that left pixel was zero. */ - (void) prev; //unused parameter - png_debug(1, "in png_read_filter_row_sub3_sse2"); + png_size_t rb; + __m128i a, d = _mm_setzero_si128(); - png_size_t rb = row_info->rowbytes; + png_debug(1, "in png_read_filter_row_sub3_sse2"); + + rb = row_info->rowbytes; while (rb >= 4) { a = d; d = load4(row); d = _mm_add_epi8(d, a); @@ -90,6 +94,7 @@ void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row, row += 3; rb -= 3; } + PNG_UNUSED(prev) } void png_read_filter_row_sub4_sse2(png_row_infop row_info, png_bytep row, @@ -99,12 +104,14 @@ void png_read_filter_row_sub4_sse2(png_row_infop row_info, png_bytep row, * There is no pixel to the left of the first pixel. It's encoded directly. * That works with our main loop if we just say that left pixel was zero. */ - (void) prev; //unused parameter - png_debug(1, "in png_read_filter_row_sub4_sse2"); + png_size_t rb; + __m128i a, d = _mm_setzero_si128(); - png_size_t rb = row_info->rowbytes; - while (rb > 0) { + png_debug(1, "in png_read_filter_row_sub4_sse2"); + + rb = row_info->rowbytes+4; + while (rb > 4) { a = d; d = load4(row); d = _mm_add_epi8(d, a); store4(row, d); @@ -112,6 +119,7 @@ void png_read_filter_row_sub4_sse2(png_row_infop row_info, png_bytep row, row += 4; rb -= 4; } + PNG_UNUSED(prev) } void png_read_filter_row_avg3_sse2(png_row_infop row_info, png_bytep row, @@ -122,18 +130,23 @@ void png_read_filter_row_avg3_sse2(png_row_infop row_info, png_bytep row, * predicted to be half of the pixel above it. So again, this works * perfectly with our loop if we make sure a starts at zero. */ - png_debug(1, "in png_read_filter_row_avg3_sse2"); + + png_size_t rb; + const __m128i zero = _mm_setzero_si128(); + __m128i b; __m128i a, d = zero; - png_size_t rb = row_info->rowbytes; + png_debug(1, "in png_read_filter_row_avg3_sse2"); + rb = row_info->rowbytes; while (rb >= 4) { + __m128i avg; b = load4(prev); a = d; d = load4(row ); /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */ - __m128i avg = _mm_avg_epu8(a,b); + avg = _mm_avg_epu8(a,b); /* ...but we can fix it up by subtracting off 1 if it rounded up. */ avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b), _mm_set1_epi8(1))); @@ -145,11 +158,12 @@ void png_read_filter_row_avg3_sse2(png_row_infop row_info, png_bytep row, rb -= 3; } if (rb > 0) { + __m128i avg; b = load3(prev); a = d; d = load3(row ); /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */ - __m128i avg = _mm_avg_epu8(a,b); + avg = _mm_avg_epu8(a,b); /* ...but we can fix it up by subtracting off 1 if it rounded up. */ avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b), _mm_set1_epi8(1))); @@ -171,18 +185,21 @@ void png_read_filter_row_avg4_sse2(png_row_infop row_info, png_bytep row, * predicted to be half of the pixel above it. So again, this works * perfectly with our loop if we make sure a starts at zero. */ - png_debug(1, "in png_read_filter_row_avg4_sse2"); + png_size_t rb; const __m128i zero = _mm_setzero_si128(); __m128i b; __m128i a, d = zero; - png_size_t rb = row_info->rowbytes; - while (rb > 0) { + png_debug(1, "in png_read_filter_row_avg4_sse2"); + + rb = row_info->rowbytes+4; + while (rb > 4) { + __m128i avg; b = load4(prev); a = d; d = load4(row ); /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */ - __m128i avg = _mm_avg_epu8(a,b); + avg = _mm_avg_epu8(a,b); /* ...but we can fix it up by subtracting off 1 if it rounded up. */ avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b), _mm_set1_epi8(1))); @@ -240,38 +257,42 @@ void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row, * Here we zero b and d, which become c and a respectively at the start of * the loop. */ - png_debug(1, "in png_read_filter_row_paeth3_sse2"); + png_size_t rb; const __m128i zero = _mm_setzero_si128(); __m128i c, b = zero, a, d = zero; - png_size_t rb = row_info->rowbytes; + png_debug(1, "in png_read_filter_row_paeth3_sse2"); + + rb = row_info->rowbytes; while (rb >= 4) { /* It's easiest to do this math (particularly, deal with pc) with 16-bit * intermediates. */ + __m128i pa,pb,pc,smallest,nearest; c = b; b = _mm_unpacklo_epi8(load4(prev), zero); a = d; d = _mm_unpacklo_epi8(load4(row ), zero); /* (p-a) == (a+b-c - a) == (b-c) */ - __m128i pa = _mm_sub_epi16(b,c); + + pa = _mm_sub_epi16(b,c); /* (p-b) == (a+b-c - b) == (a-c) */ - __m128i pb = _mm_sub_epi16(a,c); + pb = _mm_sub_epi16(a,c); /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */ - __m128i pc = _mm_add_epi16(pa,pb); + pc = _mm_add_epi16(pa,pb); pa = abs_i16(pa); /* |p-a| */ pb = abs_i16(pb); /* |p-b| */ pc = abs_i16(pc); /* |p-c| */ - __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); + smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); /* Paeth breaks ties favoring a over b over c. */ - __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, - if_then_else(_mm_cmpeq_epi16(smallest, pb), b, - c)); + nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, + if_then_else(_mm_cmpeq_epi16(smallest, pb), b, + c)); /* Note `_epi8`: we need addition to wrap modulo 255. */ d = _mm_add_epi8(d, nearest); @@ -285,26 +306,27 @@ void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row, /* It's easiest to do this math (particularly, deal with pc) with 16-bit * intermediates. */ + __m128i pa,pb,pc,smallest,nearest; c = b; b = _mm_unpacklo_epi8(load3(prev), zero); a = d; d = _mm_unpacklo_epi8(load3(row ), zero); /* (p-a) == (a+b-c - a) == (b-c) */ - __m128i pa = _mm_sub_epi16(b,c); + pa = _mm_sub_epi16(b,c); /* (p-b) == (a+b-c - b) == (a-c) */ - __m128i pb = _mm_sub_epi16(a,c); + pb = _mm_sub_epi16(a,c); /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */ - __m128i pc = _mm_add_epi16(pa,pb); + pc = _mm_add_epi16(pa,pb); pa = abs_i16(pa); /* |p-a| */ pb = abs_i16(pb); /* |p-b| */ pc = abs_i16(pc); /* |p-c| */ - __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); + smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); /* Paeth breaks ties favoring a over b over c. */ - __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, + nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, if_then_else(_mm_cmpeq_epi16(smallest, pb), b, c)); @@ -334,13 +356,16 @@ void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row, * Here we zero b and d, which become c and a respectively at the start of * the loop. */ - png_debug(1, "in png_read_filter_row_paeth4_sse2"); + png_size_t rb; const __m128i zero = _mm_setzero_si128(); + __m128i pa,pb,pc,smallest,nearest; __m128i c, b = zero, a, d = zero; - png_size_t rb = row_info->rowbytes; - while (rb > 0) { + png_debug(1, "in png_read_filter_row_paeth4_sse2"); + + rb = row_info->rowbytes+4; + while (rb > 4) { /* It's easiest to do this math (particularly, deal with pc) with 16-bit * intermediates. */ @@ -348,22 +373,22 @@ void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row, a = d; d = _mm_unpacklo_epi8(load4(row ), zero); /* (p-a) == (a+b-c - a) == (b-c) */ - __m128i pa = _mm_sub_epi16(b,c); + pa = _mm_sub_epi16(b,c); /* (p-b) == (a+b-c - b) == (a-c) */ - __m128i pb = _mm_sub_epi16(a,c); + pb = _mm_sub_epi16(a,c); /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */ - __m128i pc = _mm_add_epi16(pa,pb); + pc = _mm_add_epi16(pa,pb); pa = abs_i16(pa); /* |p-a| */ pb = abs_i16(pb); /* |p-b| */ pc = abs_i16(pc); /* |p-c| */ - __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); + smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); /* Paeth breaks ties favoring a over b over c. */ - __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, + nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, if_then_else(_mm_cmpeq_epi16(smallest, pb), b, c)); diff --git a/3rdparty/libpng/contrib/intel/intel_init.c b/3rdparty/libpng/intel/intel_init.c similarity index 86% rename from 3rdparty/libpng/contrib/intel/intel_init.c rename to 3rdparty/libpng/intel/intel_init.c index 328e90e9af..8f08baf8c5 100644 --- a/3rdparty/libpng/contrib/intel/intel_init.c +++ b/3rdparty/libpng/intel/intel_init.c @@ -1,19 +1,18 @@ /* intel_init.c - SSE2 optimized filter functions * - * Copyright (c) 2016 Google, Inc. - * Written by Mike Klein and Matt Sarett - * Derived from arm/arm_init.c, which was - * Copyright (c) 2014,2016 Glenn Randers-Pehrson + * Copyright (c) 2016-2017 Glenn Randers-Pehrson + * Written by Mike Klein and Matt Sarett, Google, Inc. + * Derived from arm/arm_init.c * - * Last changed in libpng 1.6.22 [May 26, 2016] + * Last changed in libpng 1.6.29 [March 16, 2017] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ -#include "../../pngpriv.h" +#include "../pngpriv.h" #ifdef PNG_READ_SUPPORTED #if PNG_INTEL_SSE_IMPLEMENTATION > 0 diff --git a/3rdparty/libpng/opencv-libpng.patch b/3rdparty/libpng/opencv-libpng.patch deleted file mode 100644 index b76f87c523..0000000000 --- a/3rdparty/libpng/opencv-libpng.patch +++ /dev/null @@ -1,105 +0,0 @@ -diff --git a/3rdparty/libpng/CMakeLists.txt b/3rdparty/libpng/CMakeLists.txt -index fee9c99..eaf2095 100644 ---- a/3rdparty/libpng/CMakeLists.txt -+++ b/3rdparty/libpng/CMakeLists.txt -@@ -33,6 +33,11 @@ if(ENABLE_NEON) - add_definitions(-DPNG_ARM_NEON_OPT=2) - endif() - -+if(ENABLE_SSE) -+ list(APPEND lib_srcs contrib/intel/intel_init.c contrib/intel/filter_sse2_intrinsics.c) -+ add_definitions(-DPNG_INTEL_SSE) -+endif() -+ - # ---------------------------------------------------------------------------------- - # Define the library target: - # ---------------------------------------------------------------------------------- -diff --git a/3rdparty/libpng/pngpriv.h b/3rdparty/libpng/pngpriv.h -index fe3355d..c0aa785 100644 ---- a/3rdparty/libpng/pngpriv.h -+++ b/3rdparty/libpng/pngpriv.h -@@ -182,6 +182,42 @@ - # endif - #endif /* PNG_ARM_NEON_OPT > 0 */ - -+#ifndef PNG_INTEL_SSE_OPT -+# ifdef PNG_INTEL_SSE -+ /* Only check for SSE if the build configuration has been modified to -+ * enable SSE optimizations. This means that these optimizations will -+ * be off by default. See contrib/intel for more details. -+ */ -+# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ -+ defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ -+ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) -+# define PNG_INTEL_SSE_OPT 1 -+# endif -+# endif -+#endif -+ -+#if defined(PNG_INTEL_SSE_OPT) && PNG_INTEL_SSE_OPT > 0 -+# ifndef PNG_INTEL_SSE_IMPLEMENTATION -+# if defined(__SSE4_1__) || defined(__AVX__) -+ /* We are not actually using AVX, but checking for AVX is the best -+ way we can detect SSE4.1 and SSSE3 on MSVC. -+ */ -+# define PNG_INTEL_SSE_IMPLEMENTATION 3 -+# elif defined(__SSSE3__) -+# define PNG_INTEL_SSE_IMPLEMENTATION 2 -+# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ -+ (defined(_M_IX86_FP) && _M_IX86_FP >= 2) -+# define PNG_INTEL_SSE_IMPLEMENTATION 1 -+# else -+# define PNG_INTEL_SSE_IMPLEMENTATION 0 -+# endif -+# endif -+ -+# if PNG_INTEL_SSE_IMPLEMENTATION > 0 -+# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 -+# endif -+#endif -+ - /* Is this a build of a DLL where compilation of the object modules requires - * different preprocessor settings to those required for a simple library? If - * so PNG_BUILD_DLL must be set. -@@ -457,7 +493,7 @@ - - /* Memory model/platform independent fns */ - #ifndef PNG_ABORT --# ifdef _WINDOWS_ -+# if defined(_WINDOWS_) && !defined(WINRT) - # define PNG_ABORT() ExitProcess(0) - # else - # define PNG_ABORT() abort() -@@ -1190,6 +1226,21 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop - PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); - #endif -+ -+#if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop -+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -+#endif - - /* Choose the best filter to use and filter the row data */ - PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, -@@ -1919,6 +1970,10 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr, - PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, - (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); - # endif -+# if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 -+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, -+ (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); -+# endif - #endif - - PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, diff --git a/3rdparty/libpng/png.c b/3rdparty/libpng/png.c index 0843ebbc26..ff02c56518 100644 --- a/3rdparty/libpng/png.c +++ b/3rdparty/libpng/png.c @@ -1,8 +1,8 @@ /* png.c - location for general purpose libpng functions * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson + * Last changed in libpng 1.6.33 [September 28, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -14,7 +14,27 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_24 Your_png_h_is_not_version_1_6_24; +typedef png_libpng_version_1_6_34 Your_png_h_is_not_version_1_6_34; + +#ifdef __GNUC__ +/* The version tests may need to be added to, but the problem warning has + * consistently been fixed in GCC versions which obtain wide-spread release. + * The problem is that many versions of GCC rearrange comparison expressions in + * the optimizer in such a way that the results of the comparison will change + * if signed integer overflow occurs. Such comparisons are not permitted in + * ANSI C90, however GCC isn't clever enough to work out that that do not occur + * below in png_ascii_from_fp and png_muldiv, so it produces a warning with + * -Wextra. Unfortunately this is highly dependent on the optimizer and the + * machine architecture so the warning comes and goes unpredictably and is + * impossible to "fix", even were that a good idea. + */ +#if __GNUC__ == 7 && __GNUC_MINOR__ == 1 +#define GCC_STRICT_OVERFLOW 1 +#endif /* GNU 7.1.x */ +#endif /* GNU */ +#ifndef GCC_STRICT_OVERFLOW +#define GCC_STRICT_OVERFLOW 0 +#endif /* Tells libpng that we have already handled the first "num_bytes" bytes * of the PNG file signature. If the PNG data is embedded into another @@ -458,7 +478,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, #ifdef PNG_TEXT_SUPPORTED /* Free text item num or (if num == -1) all text items */ - if (info_ptr->text != 0 && + if (info_ptr->text != NULL && ((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0) { if (num != -1) @@ -477,6 +497,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, png_free(png_ptr, info_ptr->text); info_ptr->text = NULL; info_ptr->num_text = 0; + info_ptr->max_text = 0; } } #endif @@ -541,7 +562,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, #ifdef PNG_sPLT_SUPPORTED /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ - if (info_ptr->splt_palettes != 0 && + if (info_ptr->splt_palettes != NULL && ((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0) { if (num != -1) @@ -571,7 +592,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, #endif #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED - if (info_ptr->unknown_chunks != 0 && + if (info_ptr->unknown_chunks != NULL && ((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0) { if (num != -1) @@ -594,6 +615,26 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, } #endif +#ifdef PNG_eXIf_SUPPORTED + /* Free any eXIf entry */ + if (((mask & PNG_FREE_EXIF) & info_ptr->free_me) != 0) + { +# ifdef PNG_READ_eXIf_SUPPORTED + if (info_ptr->eXIf_buf) + { + png_free(png_ptr, info_ptr->eXIf_buf); + info_ptr->eXIf_buf = NULL; + } +# endif + if (info_ptr->exif) + { + png_free(png_ptr, info_ptr->exif); + info_ptr->exif = NULL; + } + info_ptr->valid &= ~PNG_INFO_eXIf; + } +#endif + #ifdef PNG_hIST_SUPPORTED /* Free any hIST entry */ if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0) @@ -617,7 +658,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, /* Free any image bits attached to the info structure */ if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0) { - if (info_ptr->row_pointers != 0) + if (info_ptr->row_pointers != NULL) { png_uint_32 row; for (row = 0; row < info_ptr->height; row++) @@ -684,7 +725,7 @@ png_init_io(png_structrp png_ptr, png_FILE_p fp) void PNGAPI png_save_int_32(png_bytep buf, png_int_32 i) { - png_save_uint_32(buf, i); + png_save_uint_32(buf, (png_uint_32)i); } # endif @@ -775,15 +816,15 @@ png_get_copyright(png_const_structrp png_ptr) #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.24 - August 4, 2016" PNG_STRING_NEWLINE \ - "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \ + "libpng version 1.6.34 - September 29, 2017" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.6.24 - August 4, 2016\ - Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\ + return "libpng version 1.6.34 - September 29, 2017\ + Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; # endif @@ -1872,12 +1913,12 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, */ if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST) return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "invalid sRGB rendering intent"); + (png_alloc_size_t)intent, "invalid sRGB rendering intent"); if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 && colorspace->rendering_intent != intent) return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "inconsistent rendering intents"); + (png_alloc_size_t)intent, "inconsistent rendering intents"); if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0) { @@ -1931,16 +1972,49 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, static const png_byte D50_nCIEXYZ[12] = { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; -int /* PRIVATE */ -png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, +static int /* bool */ +icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length) { if (profile_length < 132) return png_icc_profile_error(png_ptr, colorspace, name, profile_length, "too short"); + return 1; +} + +#ifdef PNG_READ_iCCP_SUPPORTED +int /* PRIVATE */ +png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, + png_const_charp name, png_uint_32 profile_length) +{ + if (!icc_check_length(png_ptr, colorspace, name, profile_length)) + return 0; + + /* This needs to be here because the 'normal' check is in + * png_decompress_chunk, yet this happens after the attempt to + * png_malloc_base the required data. We only need this on read; on write + * the caller supplies the profile buffer so libpng doesn't allocate it. See + * the call to icc_check_length below (the write case). + */ +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + else if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds application limits"); +# elif PNG_USER_CHUNK_MALLOC_MAX > 0 + else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds libpng limits"); +# else /* !SET_USER_LIMITS */ + /* This will get compiled out on all 32-bit and better systems. */ + else if (PNG_SIZE_MAX < profile_length) + return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + "exceeds system limits"); +# endif /* !SET_USER_LIMITS */ return 1; } +#endif /* READ_iCCP */ int /* PRIVATE */ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, @@ -2149,15 +2223,6 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, * being in range. All defined tag types have an 8 byte header - a 4 byte * type signature then 0. */ - if ((tag_start & 3) != 0) - { - /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is - * only a warning here because libpng does not care about the - * alignment. - */ - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "ICC profile tag start not a multiple of 4"); - } /* This is a hard error; potentially it can cause read outside the * profile. @@ -2165,6 +2230,16 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, if (tag_start > profile_length || tag_length > profile_length - tag_start) return png_icc_profile_error(png_ptr, colorspace, name, tag_id, "ICC profile tag outside profile"); + + if ((tag_start & 3) != 0) + { + /* CNHP730S.icc shipped with Microsoft Windows 64 violates this; it is + * only a warning here because libpng does not care about the + * alignment. + */ + (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, + "ICC profile tag start not a multiple of 4"); + } } return 1; /* success, maybe with warnings */ @@ -2377,7 +2452,7 @@ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) return 0; - if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && + if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, color_type) != 0 && png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, @@ -2495,7 +2570,7 @@ png_check_IHDR(png_const_structrp png_ptr, error = 1; } - if (png_gt(((width + 7) & (~7)), + if (png_gt(((width + 7) & (~7U)), ((PNG_SIZE_MAX - 48 /* big_row_buf hack */ - 1) /* filter byte */ @@ -2797,7 +2872,7 @@ png_pow10(int power) if (power < 0) { if (power < DBL_MIN_10_EXP) return 0; - recip = 1, power = -power; + recip = 1; power = -power; } if (power > 0) @@ -2822,6 +2897,14 @@ png_pow10(int power) /* Function to format a floating point value in ASCII with a given * precision. */ +#if GCC_STRICT_OVERFLOW +#pragma GCC diagnostic push +/* The problem arises below with exp_b10, which can never overflow because it + * comes, originally, from frexp and is therefore limited to a range which is + * typically +/-710 (log2(DBL_MAX)/log2(DBL_MIN)). + */ +#pragma GCC diagnostic warning "-Wstrict-overflow=2" +#endif /* GCC_STRICT_OVERFLOW */ void /* PRIVATE */ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, double fp, unsigned int precision) @@ -2875,7 +2958,9 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, double test = png_pow10(exp_b10+1); if (test <= DBL_MAX) - ++exp_b10, base = test; + { + ++exp_b10; base = test; + } else break; @@ -2889,7 +2974,10 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, * test on DBL_MAX above. */ fp /= base; - while (fp >= 1) fp /= 10, ++exp_b10; + while (fp >= 1) + { + fp /= 10; ++exp_b10; + } /* Because of the code above fp may, at this point, be * less than .1, this is ok because the code below can @@ -2906,7 +2994,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ { - czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ + czero = 0U-exp_b10; /* PLUS 2 digits: TOTAL 3 */ exp_b10 = 0; /* Dot added below before first output. */ } else @@ -2940,7 +3028,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, /* Rounding up to 10, handle that here. */ if (czero > 0) { - --czero, d = 1; + --czero; d = 1; if (cdigits == 0) --clead; } else @@ -2954,7 +3042,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, else if (ch == 46) { - ch = *--ascii, ++size; + ch = *--ascii; ++size; /* Advance exp_b10 to '1', so that the * decimal point happens after the * previous digit. @@ -2981,7 +3069,9 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, int ch = *--ascii; if (ch == 46) - ++size, exp_b10 = 1; + { + ++size; exp_b10 = 1; + } /* Else lost a leading zero, so 'exp_b10' is * still ok at (-1) @@ -3017,21 +3107,26 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ if (exp_b10 != (-1)) { - if (exp_b10 == 0) *ascii++ = 46, --size; + if (exp_b10 == 0) + { + *ascii++ = 46; --size; + } /* PLUS 1: TOTAL 4 */ --exp_b10; } - *ascii++ = 48, --czero; + *ascii++ = 48; --czero; } if (exp_b10 != (-1)) { if (exp_b10 == 0) - *ascii++ = 46, --size; /* counted above */ + { + *ascii++ = 46; --size; /* counted above */ + } --exp_b10; } - *ascii++ = (char)(48 + (int)d), ++cdigits; + *ascii++ = (char)(48 + (int)d); ++cdigits; } } while (cdigits+czero < precision+clead && fp > DBL_MIN); @@ -3040,7 +3135,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, /* Check for an exponent, if we don't need one we are * done and just need to terminate the string. At - * this point exp_b10==(-1) is effectively if flag - it got + * this point exp_b10==(-1) is effectively a flag - it got * to '-1' because of the decrement after outputting * the decimal point above (the exponent required is * *not* -1!) @@ -3054,7 +3149,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, * zeros were *not* output, so this doesn't increase * the output count. */ - while (--exp_b10 >= 0) *ascii++ = 48; + while (exp_b10-- > 0) *ascii++ = 48; *ascii = 0; @@ -3072,7 +3167,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ size -= cdigits; - *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ + *ascii++ = 69; --size; /* 'E': PLUS 1 TOTAL 2+precision */ /* The following use of an unsigned temporary avoids ambiguities in * the signed arithmetic on exp_b10 and permits GCC at least to do @@ -3083,12 +3178,12 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, if (exp_b10 < 0) { - *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ - uexp_b10 = -exp_b10; + *ascii++ = 45; --size; /* '-': PLUS 1 TOTAL 3+precision */ + uexp_b10 = 0U-exp_b10; } else - uexp_b10 = exp_b10; + uexp_b10 = 0U+exp_b10; cdigits = 0; @@ -3131,6 +3226,9 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, /* Here on buffer too small. */ png_error(png_ptr, "ASCII conversion buffer too small"); } +#if GCC_STRICT_OVERFLOW +#pragma GCC diagnostic pop +#endif /* GCC_STRICT_OVERFLOW */ # endif /* FLOATING_POINT */ @@ -3150,9 +3248,11 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, /* Avoid overflow here on the minimum integer. */ if (fp < 0) - *ascii++ = 45, num = -fp; + { + *ascii++ = 45; num = (png_uint_32)(-fp); + } else - num = fp; + num = (png_uint_32)fp; if (num <= 0x80000000) /* else overflowed */ { @@ -3188,7 +3288,10 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, * then ndigits digits to first: */ i = 5; - while (ndigits < i) *ascii++ = 48, --i; + while (ndigits < i) + { + *ascii++ = 48; --i; + } while (ndigits >= first) *ascii++ = digits[--ndigits]; /* Don't output the trailing zeros! */ } @@ -3239,6 +3342,15 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text) * the nearest .00001). Overflow and divide by zero are signalled in * the result, a boolean - true on success, false on overflow. */ +#if GCC_STRICT_OVERFLOW /* from above */ +/* It is not obvious which comparison below gets optimized in such a way that + * signed overflow would change the result; looking through the code does not + * reveal any tests which have the form GCC complains about, so presumably the + * optimizer is moving an add or subtract into the 'if' somewhere. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic warning "-Wstrict-overflow=2" +#endif /* GCC_STRICT_OVERFLOW */ int png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, png_int_32 divisor) @@ -3353,6 +3465,9 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, return 0; } +#if GCC_STRICT_OVERFLOW +#pragma GCC diagnostic pop +#endif /* GCC_STRICT_OVERFLOW */ #endif /* READ_GAMMA || INCH_CONVERSIONS */ #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) @@ -3646,7 +3761,7 @@ png_log16bit(png_uint_32 x) * of getting this accuracy in practice. * * To deal with this the following exp() function works out the exponent of the - * frational part of the logarithm by using an accurate 32-bit value from the + * fractional part of the logarithm by using an accurate 32-bit value from the * top four fractional bits then multiplying in the remaining bits. */ static const png_uint_32 @@ -4225,13 +4340,13 @@ png_set_option(png_structrp png_ptr, int option, int onoff) if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT && (option & 1) == 0) { - int mask = 3 << option; - int setting = (2 + (onoff != 0)) << option; - int current = png_ptr->options; + png_uint_32 mask = 3U << option; + png_uint_32 setting = (2U + (onoff != 0)) << option; + png_uint_32 current = png_ptr->options; - png_ptr->options = (png_byte)(((current & ~mask) | setting) & 0xff); + png_ptr->options = (png_uint_32)(((current & ~mask) | setting) & 0xff); - return (current & mask) >> option; + return (int)(current & mask) >> option; } return PNG_OPTION_INVALID; @@ -4243,7 +4358,7 @@ png_set_option(png_structrp png_ptr, int option, int onoff) defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) /* sRGB conversion tables; these are machine generated with the code in * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the - * specification (see the article at http://en.wikipedia.org/wiki/SRGB) + * specification (see the article at https://en.wikipedia.org/wiki/SRGB) * is used, not the gamma=1/2.2 approximation use elsewhere in libpng. * The sRGB to linear table is exact (to the nearest 16-bit linear fraction). * The inverse (linear to sRGB) table has accuracies as follows: diff --git a/3rdparty/libpng/png.h b/3rdparty/libpng/png.h index ebfb3dd02e..4c873f5c22 100644 --- a/3rdparty/libpng/png.h +++ b/3rdparty/libpng/png.h @@ -1,9 +1,9 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.24, August 4, 2016 + * libpng version 1.6.34, September 29, 2017 * - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -12,7 +12,7 @@ * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.24, August 4, 2016: + * libpng versions 0.97, January 1998, through 1.6.34, September 29, 2017: * Glenn Randers-Pehrson. * See also "Contributing Authors", below. */ @@ -25,12 +25,8 @@ * * This code is released under the libpng license. * - * Some files in the "contrib" directory and some configure-generated - * files that are distributed with libpng have other copyright owners and - * are released under other open source licenses. - * - * libpng versions 1.0.7, July 1, 2000 through 1.6.24, August 4, 2016 are - * Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are + * libpng versions 1.0.7, July 1, 2000 through 1.6.34, September 29, 2017 are + * Copyright (c) 2000-2002, 2004, 2006-2017 Glenn Randers-Pehrson, are * derived from libpng-1.0.6, and are distributed according to the same * disclaimer and license as libpng-1.0.6 with the following individuals * added to the list of Contributing Authors: @@ -41,6 +37,9 @@ * Cosmin Truta * Gilles Vollant * James Yu + * Mandar Sahastrabuddhe + * Google Inc. + * Vadim Barkov * * and with the following additions to the disclaimer: * @@ -51,10 +50,10 @@ * risk of satisfactory quality, performance, accuracy, and effort is with * the user. * - * Some files in the "contrib" directory have other copyright owners and + * Some files in the "contrib" directory and some configure-generated + * files that are distributed with libpng have other copyright owners and * are released under other open source licenses. * - * * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from * libpng-0.96, and are distributed according to the same disclaimer and @@ -65,9 +64,6 @@ * Glenn Randers-Pehrson * Willem van Schaik * - * Some files in the "scripts" directory have different copyright owners - * but are also released under this license. - * * libpng versions 0.89, June 1996, through 0.96, May 1997, are * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, * and are distributed according to the same disclaimer and license as @@ -213,11 +209,11 @@ * ... * 1.0.19 10 10019 10.so.0.19[.0] * ... - * 1.2.56 13 10256 12.so.0.56[.0] + * 1.2.59 13 10257 12.so.0.59[.0] * ... - * 1.5.27 15 10527 15.so.15.27[.0] + * 1.5.30 15 10527 15.so.15.30[.0] * ... - * 1.6.24 16 10624 16.so.16.24[.0] + * 1.6.34 16 10633 16.so.16.34[.0] * * Henceforth the source version will match the shared-library major * and minor numbers; the shared-library major version number will be @@ -238,20 +234,20 @@ * * See libpng.txt or libpng.3 for more information. The PNG specification * is available as a W3C Recommendation and as an ISO Specification, - * 4294967294 +#if UINT_MAX > 4294967294U typedef unsigned int png_uint_32; -#elif ULONG_MAX > 4294967294 +#elif ULONG_MAX > 4294967294U typedef unsigned long int png_uint_32; #else # error "libpng requires an unsigned 32-bit (or more) type" diff --git a/3rdparty/libpng/pngerror.c b/3rdparty/libpng/pngerror.c index f13b76443a..ad48bfb986 100644 --- a/3rdparty/libpng/pngerror.c +++ b/3rdparty/libpng/pngerror.c @@ -1,8 +1,8 @@ /* pngerror.c - stub functions for i/o and memory allocation * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.31 [July 27, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -163,7 +163,7 @@ png_format_number(png_const_charp start, png_charp end, int format, case PNG_NUMBER_FORMAT_02u: /* Expects at least 2 digits. */ mincount = 2; - /* FALL THROUGH */ + /* FALLTHROUGH */ case PNG_NUMBER_FORMAT_u: *--end = digits[number % 10]; @@ -173,7 +173,7 @@ png_format_number(png_const_charp start, png_charp end, int format, case PNG_NUMBER_FORMAT_02x: /* This format expects at least two digits */ mincount = 2; - /* FALL THROUGH */ + /* FALLTHROUGH */ case PNG_NUMBER_FORMAT_x: *--end = digits[number & 0xf]; @@ -573,7 +573,7 @@ png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN) { # define fixed_message "fixed point overflow in " # define fixed_message_ln ((sizeof fixed_message)-1) - int iin; + unsigned int iin; char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; memcpy(msg, fixed_message, fixed_message_ln); iin = 0; diff --git a/3rdparty/libpng/pngget.c b/3rdparty/libpng/pngget.c index b3c6863f40..26e9fb1c35 100644 --- a/3rdparty/libpng/pngget.c +++ b/3rdparty/libpng/pngget.c @@ -1,8 +1,8 @@ /* pngget.c - retrieval of values from info struct * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.32 [August 24, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -338,7 +338,7 @@ ppi_from_ppm(png_uint_32 ppm) png_fixed_point result; if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127, 5000) != 0) - return result; + return (png_uint_32)result; /* Overflow. */ return 0; @@ -773,6 +773,35 @@ png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr, } #endif +#ifdef PNG_eXIf_SUPPORTED +png_uint_32 PNGAPI +png_get_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, + png_bytep *exif) +{ + png_warning(png_ptr, "png_get_eXIf does not work; use png_get_eXIf_1"); + PNG_UNUSED(info_ptr) + PNG_UNUSED(exif) + return 0; +} + +png_uint_32 PNGAPI +png_get_eXIf_1(png_const_structrp png_ptr, png_const_inforp info_ptr, + png_uint_32 *num_exif, png_bytep *exif) +{ + png_debug1(1, "in %s retrieval function", "eXIf"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_eXIf) != 0 && exif != NULL) + { + *num_exif = info_ptr->num_exif; + *exif = info_ptr->exif; + return (PNG_INFO_eXIf); + } + + return (0); +} +#endif + #ifdef PNG_hIST_SUPPORTED png_uint_32 PNGAPI png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr, diff --git a/3rdparty/libpng/pnginfo.h b/3rdparty/libpng/pnginfo.h index 361ed8be70..d5f6149dbd 100644 --- a/3rdparty/libpng/pnginfo.h +++ b/3rdparty/libpng/pnginfo.h @@ -185,6 +185,14 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ #endif +#ifdef PNG_eXIf_SUPPORTED + int num_exif; /* Added at libpng-1.6.31 */ + png_bytep exif; +# ifdef PNG_READ_eXIf_SUPPORTED + png_bytep eXIf_buf; /* Added at libpng-1.6.32 */ +# endif +#endif + #ifdef PNG_hIST_SUPPORTED /* The hIST chunk contains the relative frequency or importance of the * various palette entries, so that a viewer can intelligently select a diff --git a/3rdparty/libpng/pnglibconf.h b/3rdparty/libpng/pnglibconf.h index d91d9f4199..53b5e442c4 100644 --- a/3rdparty/libpng/pnglibconf.h +++ b/3rdparty/libpng/pnglibconf.h @@ -1,10 +1,10 @@ -/* libpng 1.6.24 STANDARD API DEFINITION */ +/* libpng 1.6.34 STANDARD API DEFINITION */ /* pnglibconf.h - library build configuration */ -/* Libpng version 1.6.24 - August 4, 2016 */ +/* Libpng version 1.6.34 - September 29, 2017 */ -/* Copyright (c) 1998-2015 Glenn Randers-Pehrson */ +/* Copyright (c) 1998-2017 Glenn Randers-Pehrson */ /* This code is released under the libpng license. */ /* For conditions of distribution and use, see the disclaimer */ @@ -20,6 +20,8 @@ #define PNG_ALIGNED_MEMORY_SUPPORTED /*#undef PNG_ARM_NEON_API_SUPPORTED*/ /*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ +/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ #define PNG_BENIGN_ERRORS_SUPPORTED #define PNG_BENIGN_READ_ERRORS_SUPPORTED /*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ @@ -82,6 +84,7 @@ #define PNG_READ_USER_TRANSFORM_SUPPORTED #define PNG_READ_bKGD_SUPPORTED #define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_eXIf_SUPPORTED #define PNG_READ_gAMA_SUPPORTED #define PNG_READ_hIST_SUPPORTED #define PNG_READ_iCCP_SUPPORTED @@ -151,6 +154,7 @@ #define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED #define PNG_WRITE_bKGD_SUPPORTED #define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_eXIf_SUPPORTED #define PNG_WRITE_gAMA_SUPPORTED #define PNG_WRITE_hIST_SUPPORTED #define PNG_WRITE_iCCP_SUPPORTED @@ -168,6 +172,7 @@ #define PNG_WRITE_zTXt_SUPPORTED #define PNG_bKGD_SUPPORTED #define PNG_cHRM_SUPPORTED +#define PNG_eXIf_SUPPORTED #define PNG_gAMA_SUPPORTED #define PNG_hIST_SUPPORTED #define PNG_iCCP_SUPPORTED diff --git a/3rdparty/libpng/pngmem.c b/3rdparty/libpng/pngmem.c index 6033bf2f56..ff3ef7e88c 100644 --- a/3rdparty/libpng/pngmem.c +++ b/3rdparty/libpng/pngmem.c @@ -1,7 +1,7 @@ /* pngmem.c - stub functions for memory allocation * - * Last changed in libpng 1.6.24 [August 4, 2016] + * Last changed in libpng 1.6.26 [October 20, 2016] * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -109,7 +109,7 @@ static png_voidp png_malloc_array_checked(png_const_structrp png_ptr, int nelements, size_t element_size) { - png_alloc_size_t req = nelements; /* known to be > 0 */ + png_alloc_size_t req = (png_alloc_size_t)nelements; /* known to be > 0 */ if (req <= PNG_SIZE_MAX/element_size) return png_malloc_base(png_ptr, req * element_size); diff --git a/3rdparty/libpng/pngpread.c b/3rdparty/libpng/pngpread.c index 794352f42c..fbe361dc34 100644 --- a/3rdparty/libpng/pngpread.c +++ b/3rdparty/libpng/pngpread.c @@ -1,8 +1,8 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.32 [August 24, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -189,6 +189,7 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) png_crc_read(png_ptr, chunk_tag, 4); png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_check_chunk_length(png_ptr, png_ptr->push_length); png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; } @@ -684,7 +685,12 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, png_warning(png_ptr, "Truncated compressed data in IDAT"); else - png_error(png_ptr, "Decompression error in IDAT"); + { + if (ret == Z_DATA_ERROR) + png_benign_error(png_ptr, "IDAT: ADLER32 checksum mismatch"); + else + png_error(png_ptr, "Decompression error in IDAT"); + } /* Skip the check on unprocessed input */ return; diff --git a/3rdparty/libpng/pngpriv.h b/3rdparty/libpng/pngpriv.h index c0aa785f2b..1f2e90f2b3 100644 --- a/3rdparty/libpng/pngpriv.h +++ b/3rdparty/libpng/pngpriv.h @@ -1,8 +1,8 @@ /* pngpriv.h - private declarations for use inside libpng * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.32 [August 24, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -35,7 +35,9 @@ * Windows/Visual Studio) there is no effect; the OS specific tests below are * still required (as of 2011-05-02.) */ -#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ +#endif #ifndef PNG_VERSION_INFO_ONLY /* Standard library headers not required by png.h: */ @@ -182,6 +184,22 @@ # endif #endif /* PNG_ARM_NEON_OPT > 0 */ +#ifndef PNG_MIPS_MSA_OPT +# if defined(__mips_msa) && (__mips_isa_rev >= 5) && defined(PNG_ALIGNED_MEMORY_SUPPORTED) +# define PNG_MIPS_MSA_OPT 2 +# else +# define PNG_MIPS_MSA_OPT 0 +# endif +#endif + +#ifndef PNG_POWERPC_VSX_OPT +# if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__) +# define PNG_POWERPC_VSX_OPT 2 +# else +# define PNG_POWERPC_VSX_OPT 0 +# endif +#endif + #ifndef PNG_INTEL_SSE_OPT # ifdef PNG_INTEL_SSE /* Only check for SSE if the build configuration has been modified to @@ -196,7 +214,7 @@ # endif #endif -#if defined(PNG_INTEL_SSE_OPT) && PNG_INTEL_SSE_OPT > 0 +#if PNG_INTEL_SSE_OPT > 0 # ifndef PNG_INTEL_SSE_IMPLEMENTATION # if defined(__SSE4_1__) || defined(__AVX__) /* We are not actually using AVX, but checking for AVX is the best @@ -218,6 +236,32 @@ # endif #endif +#if PNG_MIPS_MSA_OPT > 0 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa +# ifndef PNG_MIPS_MSA_IMPLEMENTATION +# if defined(__mips_msa) +# if defined(__clang__) +# elif defined(__GNUC__) +# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) +# define PNG_MIPS_MSA_IMPLEMENTATION 2 +# endif /* no GNUC support */ +# endif /* __GNUC__ */ +# else /* !defined __mips_msa */ +# define PNG_MIPS_MSA_IMPLEMENTATION 2 +# endif /* __mips_msa */ +# endif /* !PNG_MIPS_MSA_IMPLEMENTATION */ + +# ifndef PNG_MIPS_MSA_IMPLEMENTATION +# define PNG_MIPS_MSA_IMPLEMENTATION 1 +# endif +#endif /* PNG_MIPS_MSA_OPT > 0 */ + +#if PNG_POWERPC_VSX_OPT > 0 +# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx +# define PNG_POWERPC_VSX_IMPLEMENTATION 1 +#endif + + /* Is this a build of a DLL where compilation of the object modules requires * different preprocessor settings to those required for a simple library? If * so PNG_BUILD_DLL must be set. @@ -410,25 +454,6 @@ # define png_fixed_error(s1,s2) png_err(s1) #endif -/* C allows up-casts from (void*) to any pointer and (const void*) to any - * pointer to a const object. C++ regards this as a type error and requires an - * explicit, static, cast and provides the static_cast<> rune to ensure that - * const is not cast away. - */ -#ifdef __cplusplus -# define png_voidcast(type, value) static_cast(value) -# define png_constcast(type, value) const_cast(value) -# define png_aligncast(type, value) \ - static_cast(static_cast(value)) -# define png_aligncastconst(type, value) \ - static_cast(static_cast(value)) -#else -# define png_voidcast(type, value) (value) -# define png_constcast(type, value) ((type)(value)) -# define png_aligncast(type, value) ((void*)(value)) -# define png_aligncastconst(type, value) ((const void*)(value)) -#endif /* __cplusplus */ - /* Some fixed point APIs are still required even if not exported because * they get used by the corresponding floating point APIs. This magic * deals with this: @@ -443,6 +468,35 @@ /* Other defines specific to compilers can go here. Try to keep * them inside an appropriate ifdef/endif pair for portability. */ + +/* C allows up-casts from (void*) to any pointer and (const void*) to any + * pointer to a const object. C++ regards this as a type error and requires an + * explicit, static, cast and provides the static_cast<> rune to ensure that + * const is not cast away. + */ +#ifdef __cplusplus +# define png_voidcast(type, value) static_cast(value) +# define png_constcast(type, value) const_cast(value) +# define png_aligncast(type, value) \ + static_cast(static_cast(value)) +# define png_aligncastconst(type, value) \ + static_cast(static_cast(value)) +#else +# define png_voidcast(type, value) (value) +# ifdef _WIN64 +# ifdef __GNUC__ + typedef unsigned long long png_ptruint; +# else + typedef unsigned __int64 png_ptruint; +# endif +# else + typedef unsigned long png_ptruint; +# endif +# define png_constcast(type, value) ((type)(png_ptruint)(const void*)(value)) +# define png_aligncast(type, value) ((void*)(value)) +# define png_aligncastconst(type, value) ((const void*)(value)) +#endif /* __cplusplus */ + #if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) /* png.c requires the following ANSI-C constants if the conversion of @@ -493,7 +547,7 @@ /* Memory model/platform independent fns */ #ifndef PNG_ABORT -# if defined(_WINDOWS_) && !defined(WINRT) +# ifdef _WINDOWS_ # define PNG_ABORT() ExitProcess(0) # else # define PNG_ABORT() abort() @@ -540,7 +594,8 @@ /* This implicitly assumes alignment is always to a power of 2. */ #ifdef png_alignof # define png_isaligned(ptr, type)\ - ((((const char*)ptr-(const char*)0) & (png_alignof(type)-1)) == 0) + (((type)((const char*)ptr-(const char*)0) & \ + (type)(png_alignof(type)-1)) == 0) #else # define png_isaligned(ptr, type) 0 #endif @@ -557,92 +612,92 @@ * are defined in png.h because they need to be visible to applications * that call png_set_unknown_chunk(). */ -/* #define PNG_HAVE_IHDR 0x01 (defined in png.h) */ -/* #define PNG_HAVE_PLTE 0x02 (defined in png.h) */ -#define PNG_HAVE_IDAT 0x04 -/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */ -#define PNG_HAVE_IEND 0x10 - /* 0x20 (unused) */ - /* 0x40 (unused) */ - /* 0x80 (unused) */ -#define PNG_HAVE_CHUNK_HEADER 0x100 -#define PNG_WROTE_tIME 0x200 -#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 -#define PNG_BACKGROUND_IS_GRAY 0x800 -#define PNG_HAVE_PNG_SIGNATURE 0x1000 -#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ - /* 0x4000 (unused) */ -#define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */ +/* #define PNG_HAVE_IHDR 0x01U (defined in png.h) */ +/* #define PNG_HAVE_PLTE 0x02U (defined in png.h) */ +#define PNG_HAVE_IDAT 0x04U +/* #define PNG_AFTER_IDAT 0x08U (defined in png.h) */ +#define PNG_HAVE_IEND 0x10U + /* 0x20U (unused) */ + /* 0x40U (unused) */ + /* 0x80U (unused) */ +#define PNG_HAVE_CHUNK_HEADER 0x100U +#define PNG_WROTE_tIME 0x200U +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400U +#define PNG_BACKGROUND_IS_GRAY 0x800U +#define PNG_HAVE_PNG_SIGNATURE 0x1000U +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */ + /* 0x4000U (unused) */ +#define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */ /* Flags for the transformations the PNG library does on the image data */ -#define PNG_BGR 0x0001 -#define PNG_INTERLACE 0x0002 -#define PNG_PACK 0x0004 -#define PNG_SHIFT 0x0008 -#define PNG_SWAP_BYTES 0x0010 -#define PNG_INVERT_MONO 0x0020 -#define PNG_QUANTIZE 0x0040 -#define PNG_COMPOSE 0x0080 /* Was PNG_BACKGROUND */ -#define PNG_BACKGROUND_EXPAND 0x0100 -#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ -#define PNG_16_TO_8 0x0400 /* Becomes 'chop' in 1.5.4 */ -#define PNG_RGBA 0x0800 -#define PNG_EXPAND 0x1000 -#define PNG_GAMMA 0x2000 -#define PNG_GRAY_TO_RGB 0x4000 -#define PNG_FILLER 0x8000 -#define PNG_PACKSWAP 0x10000 -#define PNG_SWAP_ALPHA 0x20000 -#define PNG_STRIP_ALPHA 0x40000 -#define PNG_INVERT_ALPHA 0x80000 -#define PNG_USER_TRANSFORM 0x100000 -#define PNG_RGB_TO_GRAY_ERR 0x200000 -#define PNG_RGB_TO_GRAY_WARN 0x400000 -#define PNG_RGB_TO_GRAY 0x600000 /* two bits, RGB_TO_GRAY_ERR|WARN */ -#define PNG_ENCODE_ALPHA 0x800000 /* Added to libpng-1.5.4 */ -#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */ -#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */ -#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */ - /* 0x8000000 unused */ - /* 0x10000000 unused */ - /* 0x20000000 unused */ - /* 0x40000000 unused */ +#define PNG_BGR 0x0001U +#define PNG_INTERLACE 0x0002U +#define PNG_PACK 0x0004U +#define PNG_SHIFT 0x0008U +#define PNG_SWAP_BYTES 0x0010U +#define PNG_INVERT_MONO 0x0020U +#define PNG_QUANTIZE 0x0040U +#define PNG_COMPOSE 0x0080U /* Was PNG_BACKGROUND */ +#define PNG_BACKGROUND_EXPAND 0x0100U +#define PNG_EXPAND_16 0x0200U /* Added to libpng 1.5.2 */ +#define PNG_16_TO_8 0x0400U /* Becomes 'chop' in 1.5.4 */ +#define PNG_RGBA 0x0800U +#define PNG_EXPAND 0x1000U +#define PNG_GAMMA 0x2000U +#define PNG_GRAY_TO_RGB 0x4000U +#define PNG_FILLER 0x8000U +#define PNG_PACKSWAP 0x10000U +#define PNG_SWAP_ALPHA 0x20000U +#define PNG_STRIP_ALPHA 0x40000U +#define PNG_INVERT_ALPHA 0x80000U +#define PNG_USER_TRANSFORM 0x100000U +#define PNG_RGB_TO_GRAY_ERR 0x200000U +#define PNG_RGB_TO_GRAY_WARN 0x400000U +#define PNG_RGB_TO_GRAY 0x600000U /* two bits, RGB_TO_GRAY_ERR|WARN */ +#define PNG_ENCODE_ALPHA 0x800000U /* Added to libpng-1.5.4 */ +#define PNG_ADD_ALPHA 0x1000000U /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000U /* Added to libpng-1.2.9 */ +#define PNG_SCALE_16_TO_8 0x4000000U /* Added to libpng-1.5.4 */ + /* 0x8000000U unused */ + /* 0x10000000U unused */ + /* 0x20000000U unused */ + /* 0x40000000U unused */ /* Flags for png_create_struct */ -#define PNG_STRUCT_PNG 0x0001 -#define PNG_STRUCT_INFO 0x0002 +#define PNG_STRUCT_PNG 0x0001U +#define PNG_STRUCT_INFO 0x0002U /* Flags for the png_ptr->flags rather than declaring a byte for each one */ -#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 -#define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002 /* Added to libpng-1.6.0 */ - /* 0x0004 unused */ -#define PNG_FLAG_ZSTREAM_ENDED 0x0008 /* Added to libpng-1.6.0 */ - /* 0x0010 unused */ - /* 0x0020 unused */ -#define PNG_FLAG_ROW_INIT 0x0040 -#define PNG_FLAG_FILLER_AFTER 0x0080 -#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 -#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 -#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 -#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 -#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */ -#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */ -#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */ -/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000 */ -/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000 */ -#define PNG_FLAG_LIBRARY_MISMATCH 0x20000 -#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000 -#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000 -#define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000 /* Added to libpng-1.4.0 */ -#define PNG_FLAG_APP_WARNINGS_WARN 0x200000 /* Added to libpng-1.6.0 */ -#define PNG_FLAG_APP_ERRORS_WARN 0x400000 /* Added to libpng-1.6.0 */ - /* 0x800000 unused */ - /* 0x1000000 unused */ - /* 0x2000000 unused */ - /* 0x4000000 unused */ - /* 0x8000000 unused */ - /* 0x10000000 unused */ - /* 0x20000000 unused */ - /* 0x40000000 unused */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001U +#define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002U /* Added to libpng-1.6.0 */ + /* 0x0004U unused */ +#define PNG_FLAG_ZSTREAM_ENDED 0x0008U /* Added to libpng-1.6.0 */ + /* 0x0010U unused */ + /* 0x0020U unused */ +#define PNG_FLAG_ROW_INIT 0x0040U +#define PNG_FLAG_FILLER_AFTER 0x0080U +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100U +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200U +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400U +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800U +#define PNG_FLAG_ASSUME_sRGB 0x1000U /* Added to libpng-1.5.4 */ +#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000U /* Added to libpng-1.5.4 */ +#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000U /* Added to libpng-1.5.4 */ +/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000U */ +/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000U */ +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000U +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000U +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000U +#define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000U /* Added to libpng-1.4.0 */ +#define PNG_FLAG_APP_WARNINGS_WARN 0x200000U /* Added to libpng-1.6.0 */ +#define PNG_FLAG_APP_ERRORS_WARN 0x400000U /* Added to libpng-1.6.0 */ + /* 0x800000U unused */ + /* 0x1000000U unused */ + /* 0x2000000U unused */ + /* 0x4000000U unused */ + /* 0x8000000U unused */ + /* 0x10000000U unused */ + /* 0x20000000U unused */ + /* 0x40000000U unused */ #define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ PNG_FLAG_CRC_ANCILLARY_NOWARN) @@ -676,6 +731,24 @@ ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) +/* This returns the number of trailing bits in the last byte of a row, 0 if the + * last byte is completely full of pixels. It is, in principle, (pixel_bits x + * width) % 8, but that would overflow for large 'width'. The second macro is + * the same except that it returns the number of unused bits in the last byte; + * (8-TRAILBITS), but 0 when TRAILBITS is 0. + * + * NOTE: these macros are intended to be self-evidently correct and never + * overflow on the assumption that pixel_bits is in the range 0..255. The + * arguments are evaluated only once and they can be signed (e.g. as a result of + * the integral promotions). The result of the expression always has type + * (png_uint_32), however the compiler always knows it is in the range 0..7. + */ +#define PNG_TRAILBITS(pixel_bits, width) \ + (((pixel_bits) * ((width) % (png_uint_32)8)) % 8) + +#define PNG_PADBITS(pixel_bits, width) \ + ((8 - PNG_TRAILBITS(pixel_bits, width)) % 8) + /* PNG_OUT_OF_RANGE returns true if value is outside the range * ideal-delta..ideal+delta. Each argument is evaluated twice. * "ideal" and "delta" should be constants, normally simple @@ -769,6 +842,7 @@ #define png_PLTE PNG_U32( 80, 76, 84, 69) #define png_bKGD PNG_U32( 98, 75, 71, 68) #define png_cHRM PNG_U32( 99, 72, 82, 77) +#define png_eXIf PNG_U32(101, 88, 73, 102) /* registered July 2017 */ #define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */ #define png_gAMA PNG_U32(103, 65, 77, 65) #define png_gIFg PNG_U32(103, 73, 70, 103) @@ -1069,6 +1143,11 @@ PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr, int intent),PNG_EMPTY); #endif +#ifdef PNG_WRITE_eXIf_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_eXIf,(png_structrp png_ptr, + png_bytep exif, int num_exif),PNG_EMPTY); +#endif + #ifdef PNG_WRITE_iCCP_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr, png_const_charp name, png_const_bytep profile), PNG_EMPTY); @@ -1226,8 +1305,42 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); #endif - -#if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 + +#if PNG_MIPS_MSA_OPT > 0 +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_msa,(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_msa,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif + +#if PNG_POWERPC_VSX_OPT > 0 +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vsx,(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); +#endif + +#if PNG_INTEL_SSE_IMPLEMENTATION > 0 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop @@ -1268,7 +1381,7 @@ PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr), /* Initialize the row buffers, etc. */ PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY); -#if PNG_ZLIB_VERNUM >= 0x1240 +#if ZLIB_VERNUM >= 0x1240 PNG_INTERNAL_FUNCTION(int,png_zlib_inflate,(png_structrp png_ptr, int flush), PNG_EMPTY); # define PNG_INFLATE(pp, flush) png_zlib_inflate(pp, flush) @@ -1334,6 +1447,11 @@ PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); #endif +#ifdef PNG_READ_eXIf_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_handle_eXIf,(png_structrp png_ptr, + png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); +#endif + #ifdef PNG_READ_gAMA_SUPPORTED PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); @@ -1409,8 +1527,11 @@ PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); #endif -PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_structrp png_ptr, - png_uint_32 chunk_name),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_const_structrp png_ptr, + const png_uint_32 chunk_name),PNG_EMPTY); + +PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr, + const png_uint_32 chunk_length),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY); @@ -1545,9 +1666,11 @@ PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr, /* The 'name' is used for information only */ /* Routines for checking parts of an ICC profile. */ +#ifdef PNG_READ_iCCP_SUPPORTED PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length), PNG_EMPTY); +#endif /* READ_iCCP */ PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length, @@ -1969,8 +2092,14 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr, # if PNG_ARM_NEON_OPT > 0 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); -# endif -# if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 +#endif + +#if PNG_MIPS_MSA_OPT > 0 +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +#endif + +# if PNG_INTEL_SSE_IMPLEMENTATION > 0 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); # endif diff --git a/3rdparty/libpng/pngread.c b/3rdparty/libpng/pngread.c index 1000326922..da32e9ad9c 100644 --- a/3rdparty/libpng/pngread.c +++ b/3rdparty/libpng/pngread.c @@ -1,8 +1,8 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.33 [September 28, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -175,6 +175,11 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) png_handle_cHRM(png_ptr, info_ptr, length); #endif +#ifdef PNG_READ_eXIf_SUPPORTED + else if (chunk_name == png_eXIf) + png_handle_eXIf(png_ptr, info_ptr, length); +#endif + #ifdef PNG_READ_gAMA_SUPPORTED else if (chunk_name == png_gAMA) png_handle_gAMA(png_ptr, info_ptr, length); @@ -359,9 +364,9 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row) for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) { - png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); - png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); - png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 s0 = (png_uint_32)(*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5); png_uint_32 red = (s0 + s1 + 65536) & 0xffff; png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; *(rp ) = (png_byte)((red >> 8) & 0xff); @@ -534,6 +539,7 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) png_error(png_ptr, "Invalid attempt to read row data"); /* Fill the row with IDAT data: */ + png_ptr->row_buf[0]=255; /* to force error if no data was found */ png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1); if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) @@ -842,6 +848,11 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) png_handle_cHRM(png_ptr, info_ptr, length); #endif +#ifdef PNG_READ_eXIf_SUPPORTED + else if (chunk_name == png_eXIf) + png_handle_eXIf(png_ptr, info_ptr, length); +#endif + #ifdef PNG_READ_gAMA_SUPPORTED else if (chunk_name == png_gAMA) png_handle_gAMA(png_ptr, info_ptr, length); @@ -1393,7 +1404,9 @@ png_image_read_header(png_voidp argument) png_structrp png_ptr = image->opaque->png_ptr; png_inforp info_ptr = image->opaque->info_ptr; +#ifdef PNG_BENIGN_ERRORS_SUPPORTED png_set_benign_errors(png_ptr, 1/*warn*/); +#endif png_read_info(png_ptr, info_ptr); /* Do this the fast way; just read directly out of png_struct. */ @@ -1431,7 +1444,7 @@ png_image_read_header(png_voidp argument) break; case PNG_COLOR_TYPE_PALETTE: - cmap_entries = png_ptr->num_palette; + cmap_entries = (png_uint_32)png_ptr->num_palette; break; default: @@ -1881,7 +1894,7 @@ png_create_colormap_entry(png_image_read_control *display, { case 4: entry[afirst ? 0 : 3] = (png_uint_16)alpha; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 3: if (alpha < 65535) @@ -1903,7 +1916,7 @@ png_create_colormap_entry(png_image_read_control *display, case 2: entry[1 ^ afirst] = (png_uint_16)alpha; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 1: if (alpha < 65535) @@ -1932,6 +1945,7 @@ png_create_colormap_entry(png_image_read_control *display, { case 4: entry[afirst ? 0 : 3] = (png_byte)alpha; + /* FALLTHROUGH */ case 3: entry[afirst + (2 ^ bgr)] = (png_byte)blue; entry[afirst + 1] = (png_byte)green; @@ -1940,6 +1954,7 @@ png_create_colormap_entry(png_image_read_control *display, case 2: entry[1 ^ afirst] = (png_byte)alpha; + /* FALLTHROUGH */ case 1: entry[afirst] = (png_byte)green; break; @@ -1966,7 +1981,7 @@ make_gray_file_colormap(png_image_read_control *display) for (i=0; i<256; ++i) png_create_colormap_entry(display, i, i, i, i, 255, P_FILE); - return i; + return (int)i; } static int @@ -1977,7 +1992,7 @@ make_gray_colormap(png_image_read_control *display) for (i=0; i<256; ++i) png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB); - return i; + return (int)i; } #define PNG_GRAY_COLORMAP_ENTRIES 256 @@ -2031,7 +2046,7 @@ make_ga_colormap(png_image_read_control *display) P_sRGB); } - return i; + return (int)i; } #define PNG_GA_COLORMAP_ENTRIES 256 @@ -2056,7 +2071,7 @@ make_rgb_colormap(png_image_read_control *display) } } - return i; + return (int)i; } #define PNG_RGB_COLORMAP_ENTRIES 216 @@ -2249,7 +2264,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) png_error(png_ptr, "gray[16] color-map: too few entries"); - cmap_entries = make_gray_colormap(display); + cmap_entries = (unsigned int)make_gray_colormap(display); if (png_ptr->num_trans > 0) { @@ -2347,7 +2362,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) png_error(png_ptr, "gray+alpha color-map: too few entries"); - cmap_entries = make_ga_colormap(display); + cmap_entries = (unsigned int)make_ga_colormap(display); background_index = PNG_CMAP_GA_BACKGROUND; output_processing = PNG_CMAP_GA; @@ -2381,7 +2396,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) png_error(png_ptr, "gray-alpha color-map: too few entries"); - cmap_entries = make_gray_colormap(display); + cmap_entries = (unsigned int)make_gray_colormap(display); if (output_encoding == P_LINEAR) { @@ -2520,7 +2535,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) png_error(png_ptr, "rgb[ga] color-map: too few entries"); - cmap_entries = make_ga_colormap(display); + cmap_entries = (unsigned int)make_ga_colormap(display); background_index = PNG_CMAP_GA_BACKGROUND; output_processing = PNG_CMAP_GA; } @@ -2546,12 +2561,12 @@ png_image_read_colormap(png_voidp argument) png_ptr->num_trans > 0) && png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0) { - cmap_entries = make_gray_file_colormap(display); + cmap_entries = (unsigned int)make_gray_file_colormap(display); data_encoding = P_FILE; } else - cmap_entries = make_gray_colormap(display); + cmap_entries = (unsigned int)make_gray_colormap(display); /* But if the input has alpha or transparency it must be removed */ @@ -2639,7 +2654,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) png_error(png_ptr, "rgb+alpha color-map: too few entries"); - cmap_entries = make_rgb_colormap(display); + cmap_entries = (unsigned int)make_rgb_colormap(display); /* Add a transparent entry. */ png_create_colormap_entry(display, cmap_entries, 255, 255, @@ -2688,7 +2703,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) png_error(png_ptr, "rgb-alpha color-map: too few entries"); - cmap_entries = make_rgb_colormap(display); + cmap_entries = (unsigned int)make_rgb_colormap(display); png_create_colormap_entry(display, cmap_entries, back_r, back_g, back_b, 0/*unused*/, output_encoding); @@ -2773,7 +2788,7 @@ png_image_read_colormap(png_voidp argument) if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries) png_error(png_ptr, "rgb color-map: too few entries"); - cmap_entries = make_rgb_colormap(display); + cmap_entries = (unsigned int)make_rgb_colormap(display); output_processing = PNG_CMAP_RGB; } } @@ -2797,11 +2812,11 @@ png_image_read_colormap(png_voidp argument) output_processing = PNG_CMAP_NONE; data_encoding = P_FILE; /* Don't change from color-map indices */ - cmap_entries = png_ptr->num_palette; + cmap_entries = (unsigned int)png_ptr->num_palette; if (cmap_entries > 256) cmap_entries = 256; - if (cmap_entries > image->colormap_entries) + if (cmap_entries > (unsigned int)image->colormap_entries) png_error(png_ptr, "palette color-map: too few entries"); for (i=0; i < cmap_entries; ++i) @@ -2859,7 +2874,7 @@ png_image_read_colormap(png_voidp argument) case P_sRGB: /* Change to 8-bit sRGB */ png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); - /* FALL THROUGH */ + /* FALLTHROUGH */ case P_FILE: if (png_ptr->bit_depth > 8) @@ -2913,7 +2928,7 @@ png_image_read_colormap(png_voidp argument) png_error(png_ptr, "bad background index (internal error)"); } - display->colormap_processing = output_processing; + display->colormap_processing = (int)output_processing; return 1/*ok*/; } @@ -3177,8 +3192,7 @@ png_image_read_colormapped(png_voidp argument) image->colormap_entries == 244 /* 216 + 1 + 27 */) break; - /* goto bad_output; */ - /* FALL THROUGH */ + goto bad_output; default: bad_output: @@ -3222,14 +3236,14 @@ png_image_read_colormapped(png_voidp argument) else { - png_alloc_size_t row_bytes = display->row_bytes; + png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes; while (--passes >= 0) { png_uint_32 y = image->height; png_bytep row = png_voidcast(png_bytep, display->first_row); - while (y-- > 0) + for (; y > 0; --y) { png_read_row(png_ptr, row, NULL); row += row_bytes; @@ -3557,8 +3571,9 @@ png_image_read_background(png_voidp argument) * stride which was multiplied by 2 (below) to get row_bytes. */ ptrdiff_t step_row = display->row_bytes / 2; - int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; - unsigned int outchannels = 1+preserve_alpha; + unsigned int preserve_alpha = (image->format & + PNG_FORMAT_FLAG_ALPHA) != 0; + unsigned int outchannels = 1U+preserve_alpha; int swap_alpha = 0; # ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED @@ -3744,7 +3759,13 @@ png_image_read_direct(png_voidp argument) mode = PNG_ALPHA_PNG; output_gamma = PNG_DEFAULT_sRGB; } - + + if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) + { + mode = PNG_ALPHA_OPTIMIZED; + change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA; + } + /* If 'do_local_background' is set check for the presence of gamma * correction; this is part of the work-round for the libpng bug * described above. @@ -3970,6 +3991,10 @@ png_image_read_direct(png_voidp argument) else if (do_local_compose != 0) /* internal error */ png_error(png_ptr, "png_image_read: alpha channel lost"); + if ((format & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) { + info_format |= PNG_FORMAT_FLAG_ASSOCIATED_ALPHA; + } + if (info_ptr->bit_depth == 16) info_format |= PNG_FORMAT_FLAG_LINEAR; @@ -4055,14 +4080,14 @@ png_image_read_direct(png_voidp argument) else { - png_alloc_size_t row_bytes = display->row_bytes; + png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes; while (--passes >= 0) { png_uint_32 y = image->height; png_bytep row = png_voidcast(png_bytep, display->first_row); - while (y-- > 0) + for (; y > 0; --y) { png_read_row(png_ptr, row, NULL); row += row_bytes; @@ -4091,7 +4116,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background, * bits; this is just to verify that the 'row_stride' argument can be * represented. */ - if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */ + if (image->width <= 0x7fffffffU/channels) /* no overflow */ { png_uint_32 check; const png_uint_32 png_row_stride = image->width * channels; @@ -4100,10 +4125,10 @@ png_image_finish_read(png_imagep image, png_const_colorp background, row_stride = (png_int_32)/*SAFE*/png_row_stride; if (row_stride < 0) - check = -row_stride; + check = (png_uint_32)(-row_stride); else - check = row_stride; + check = (png_uint_32)row_stride; /* This verifies 'check', the absolute value of the actual stride * passed in and detects overflow in the application calculation (i.e. @@ -4128,7 +4153,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background, * accomodated on 64-bit systems. */ if (image->height <= - 0xFFFFFFFFU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check) + 0xffffffffU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check) { if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || (image->colormap_entries > 0 && colormap != NULL)) diff --git a/3rdparty/libpng/pngrtran.c b/3rdparty/libpng/pngrtran.c index 748ffb3ed4..c189650313 100644 --- a/3rdparty/libpng/pngrtran.c +++ b/3rdparty/libpng/pngrtran.c @@ -1,8 +1,8 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.33 [September 28, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -49,6 +49,7 @@ png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action) case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ png_warning(png_ptr, "Can't discard critical data on CRC error"); + /* FALLTHROUGH */ case PNG_CRC_ERROR_QUIT: /* Error/quit */ case PNG_CRC_DEFAULT: @@ -429,7 +430,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, int i; png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); for (i = 0; i < num_palette; i++) png_ptr->quantize_index[i] = (png_byte)i; } @@ -446,7 +447,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, /* Initialize an array to sort colors */ png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte)))); /* Initialize the quantize_sort array */ for (i = 0; i < num_palette; i++) @@ -580,9 +581,11 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, /* Initialize palette index arrays */ png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * + (sizeof (png_byte)))); png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * (sizeof (png_byte)))); + (png_alloc_size_t)((png_uint_32)num_palette * + (sizeof (png_byte)))); /* Initialize the sort array */ for (i = 0; i < num_palette; i++) @@ -591,7 +594,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, png_ptr->palette_to_index[i] = (png_byte)i; } - hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * + hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 * (sizeof (png_dsortp)))); num_new_palette = num_palette; @@ -622,7 +625,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, { t = (png_dsortp)png_malloc_warn(png_ptr, - (png_uint_32)(sizeof (png_dsort))); + (png_alloc_size_t)(sizeof (png_dsort))); if (t == NULL) break; @@ -747,9 +750,9 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, png_size_t num_entries = ((png_size_t)1 << total_bits); png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, - (png_uint_32)(num_entries * (sizeof (png_byte)))); + (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); - distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries * (sizeof (png_byte)))); memset(distance, 0xff, num_entries * (sizeof (png_byte))); @@ -1253,7 +1256,7 @@ png_init_rgb_transformations(png_structrp png_ptr) default: case 8: - /* FALL THROUGH (Already 8 bits) */ + /* FALLTHROUGH */ /* (Already 8 bits) */ case 16: /* Already a full 16 bits */ @@ -2150,7 +2153,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row) { png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + png_uint_32 shift = 7U - ((row_width + 7U) & 0x07); for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0x01); @@ -2174,7 +2177,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row) png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1); for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0x03); @@ -2197,7 +2200,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row) { png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); png_bytep dp = row + (png_size_t)row_width - 1; - png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2); for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0x0f); @@ -2934,7 +2937,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) * using the equation given in Poynton's ColorFAQ of 1998-01-04 at * (THIS LINK IS DEAD June 2008 but * versions dated 1998 through November 2002 have been archived at - * http://web.archive.org/web/20000816232553/http://www.inforamp.net/ + * https://web.archive.org/web/20000816232553/www.inforamp.net/ * ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) * Charles Poynton poynton at poynton.com * @@ -3223,7 +3226,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) == png_ptr->trans_color.gray) { unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); - tmp |= png_ptr->background.gray << shift; + tmp |= + (unsigned int)(png_ptr->background.gray << shift); *sp = (png_byte)(tmp & 0xff); } @@ -3252,7 +3256,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) == png_ptr->trans_color.gray) { unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= png_ptr->background.gray << shift; + tmp |= + (unsigned int)png_ptr->background.gray << shift; *sp = (png_byte)(tmp & 0xff); } @@ -3262,7 +3267,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) unsigned int g = (gamma_table [p | (p << 2) | (p << 4) | (p << 6)] >> 6) & 0x03; unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= g << shift; + tmp |= (unsigned int)(g << shift); *sp = (png_byte)(tmp & 0xff); } @@ -3288,7 +3293,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) == png_ptr->trans_color.gray) { unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= png_ptr->background.gray << shift; + tmp |= + (unsigned int)png_ptr->background.gray << shift; *sp = (png_byte)(tmp & 0xff); } @@ -3318,7 +3324,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) == png_ptr->trans_color.gray) { unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= png_ptr->background.gray << shift; + tmp |= + (unsigned int)(png_ptr->background.gray << shift); *sp = (png_byte)(tmp & 0xff); } @@ -3328,7 +3335,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) unsigned int g = (gamma_table[p | (p << 4)] >> 4) & 0x0f; unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= g << shift; + tmp |= (unsigned int)(g << shift); *sp = (png_byte)(tmp & 0xff); } @@ -3354,7 +3361,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) == png_ptr->trans_color.gray) { unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= png_ptr->background.gray << shift; + tmp |= + (unsigned int)(png_ptr->background.gray << shift); *sp = (png_byte)(tmp & 0xff); } @@ -4297,7 +4305,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, if (num_trans > 0) { sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 2) - 1; + dp = row + ((png_size_t)row_width << 2) - 1; for (i = 0; i < row_width; i++) { @@ -4458,7 +4466,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, { gray = gray & 0xff; sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 1) - 1; + dp = row + ((png_size_t)row_width << 1) - 1; for (i = 0; i < row_width; i++) { @@ -4514,7 +4522,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, png_byte green = (png_byte)(trans_color->green & 0xff); png_byte blue = (png_byte)(trans_color->blue & 0xff); sp = row + (png_size_t)row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 2) - 1; + dp = row + ((png_size_t)row_width << 2) - 1; for (i = 0; i < row_width; i++) { if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) @@ -4537,7 +4545,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, png_byte green_low = (png_byte)(trans_color->green & 0xff); png_byte blue_low = (png_byte)(trans_color->blue & 0xff); sp = row + row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 3) - 1; + dp = row + ((png_size_t)row_width << 3) - 1; for (i = 0; i < row_width; i++) { if (*(sp - 5) == red_high && @@ -4596,7 +4604,9 @@ png_do_expand_16(png_row_infop row_info, png_bytep row) png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ while (dp > sp) - dp[-2] = dp[-1] = *--sp, dp -= 2; + { + dp[-2] = dp[-1] = *--sp; dp -= 2; + } row_info->rowbytes *= 2; row_info->bit_depth = 16; diff --git a/3rdparty/libpng/pngrutil.c b/3rdparty/libpng/pngrutil.c index 1c8a179443..8692933bd8 100644 --- a/3rdparty/libpng/pngrutil.c +++ b/3rdparty/libpng/pngrutil.c @@ -1,8 +1,8 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.33 [September 28, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -86,7 +86,7 @@ png_get_int_32)(png_const_bytep buf) { png_uint_32 uval = png_get_uint_32(buf); if ((uval & 0x80000000) == 0) /* non-negative */ - return uval; + return (png_int_32)uval; uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */ if ((uval & 0x80000000) == 0) /* no overflow */ @@ -181,6 +181,9 @@ png_read_chunk_header(png_structrp png_ptr) /* Check to see if chunk name is valid. */ png_check_chunk_name(png_ptr, png_ptr->chunk_name); + /* Check for too-large chunk length */ + png_check_chunk_length(png_ptr, length); + #ifdef PNG_IO_STATE_SUPPORTED png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; #endif @@ -311,6 +314,7 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn) if (buffer != NULL) { + memset(buffer, 0, new_size); /* just in case */ png_ptr->read_buffer = buffer; png_ptr->read_buffer_size = new_size; } @@ -370,11 +374,10 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) */ { int ret; /* zlib return code */ -#if PNG_ZLIB_VERNUM >= 0x1240 +#if ZLIB_VERNUM >= 0x1240 + int window_bits = 0; # if defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_MAXIMUM_INFLATE_WINDOW) - int window_bits; - if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) == PNG_OPTION_ON) { @@ -384,13 +387,11 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) else { - window_bits = 0; png_ptr->zstream_start = 1; } -# else -# define window_bits 0 # endif -#endif + +#endif /* ZLIB_VERNUM >= 0x1240 */ /* Set this for safety, just in case the previous owner left pointers to * memory allocations. @@ -402,25 +403,32 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0) { -#if PNG_ZLIB_VERNUM < 0x1240 - ret = inflateReset(&png_ptr->zstream); -#else +#if ZLIB_VERNUM >= 0x1240 ret = inflateReset2(&png_ptr->zstream, window_bits); +#else + ret = inflateReset(&png_ptr->zstream); #endif } else { -#if PNG_ZLIB_VERNUM < 0x1240 - ret = inflateInit(&png_ptr->zstream); -#else +#if ZLIB_VERNUM >= 0x1240 ret = inflateInit2(&png_ptr->zstream, window_bits); +#else + ret = inflateInit(&png_ptr->zstream); #endif if (ret == Z_OK) png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; } +#if ZLIB_VERNUM >= 0x1290 && \ + defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_IGNORE_ADLER32) + if (((png_ptr->options >> PNG_IGNORE_ADLER32) & 3) == PNG_OPTION_ON) + /* Turn off validation of the ADLER32 checksum in IDAT chunks */ + ret = inflateValidate(&png_ptr->zstream, 0); +#endif + if (ret == Z_OK) png_ptr->zowner = owner; @@ -435,7 +443,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) #endif } -#if PNG_ZLIB_VERNUM >= 0x1240 +#if ZLIB_VERNUM >= 0x1240 /* Handle the start of the inflate stream if we called inflateInit2(strm,0); * in this case some zlib versions skip validation of the CINFO field and, in * certain circumstances, libpng may end up displaying an invalid image, in @@ -461,6 +469,7 @@ png_zlib_inflate(png_structrp png_ptr, int flush) #endif /* Zlib >= 1.2.4 */ #ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED +#if defined(PNG_READ_zTXt_SUPPORTED) || defined (PNG_READ_iTXt_SUPPORTED) /* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to * allow the caller to do multiple calls if required. If the 'finish' flag is * set Z_FINISH will be passed to the final inflate() call and Z_STREAM_END must @@ -590,7 +599,6 @@ png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, } } -#if defined(PNG_READ_zTXt_SUPPORTED) || defined (PNG_READ_iTXt_SUPPORTED) /* * Decompress trailing data in a chunk. The assumption is that read_buffer * points at an allocated area holding the contents of a chunk with a @@ -666,6 +674,8 @@ png_decompress_chunk(png_structrp png_ptr, if (text != NULL) { + memset(text, 0, buffer_size); + ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, png_ptr->read_buffer + prefix_size, &lzsize, text + prefix_size, newlength); @@ -713,7 +723,7 @@ png_decompress_chunk(png_structrp png_ptr, * the extra space may otherwise be used as a Trojan Horse. */ if (ret == Z_STREAM_END && - chunklength - prefix_size != lzsize) + chunklength - prefix_size != lzsize) png_chunk_benign_error(png_ptr, "extra compressed data"); } @@ -729,9 +739,7 @@ png_decompress_chunk(png_structrp png_ptr, { /* inflateReset failed, store the error message */ png_zstream_error(png_ptr, ret); - - if (ret == Z_STREAM_END) - ret = PNG_UNEXPECTED_ZLIB_RETURN; + ret = PNG_UNEXPECTED_ZLIB_RETURN; } } @@ -823,7 +831,7 @@ png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, return Z_STREAM_ERROR; } } -#endif +#endif /* READ_iCCP */ /* Read and check the IDHR chunk */ @@ -1011,7 +1019,7 @@ png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) #endif { - png_crc_finish(png_ptr, (int) length - num * 3); + png_crc_finish(png_ptr, (png_uint_32) (length - (unsigned int)num * 3)); } #ifndef PNG_READ_OPT_PLTE_SUPPORTED @@ -1373,11 +1381,13 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) * chunk is just ignored, so does not invalidate the color space. An * alternative is to set the 'invalid' flags at the start of this routine * and only clear them in they were not set before and all the tests pass. - * The minimum 'deflate' stream is assumed to be just the 2 byte header and - * 4 byte checksum. The keyword must be at least one character and there is - * a terminator (0) byte and the compression method. */ - if (length < 9) + + /* The keyword must be at least one character and there is a + * terminator (0) byte and the compression method byte, and the + * 'zlib' datastream is at least 11 bytes. + */ + if (length < 14) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "too short"); @@ -1409,6 +1419,16 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_crc_read(png_ptr, (png_bytep)keyword, read_length); length -= read_length; + /* The minimum 'zlib' stream is assumed to be just the 2 byte header, + * 5 bytes minimum 'deflate' stream, and the 4 byte checksum. + */ + if (length < 11) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too short"); + return; + } + keyword_length = 0; while (keyword_length < 80 && keyword_length < read_length && keyword[keyword_length] != 0) @@ -1427,7 +1447,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK) { - Byte profile_header[132]; + Byte profile_header[132]={0}; Byte local_buffer[PNG_INFLATE_BUF_SIZE]; png_alloc_size_t size = (sizeof profile_header); @@ -1457,7 +1477,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) /* Now read the tag table; a variable size buffer is * needed at this point, allocate one for the whole * profile. The header check has already validated - * that none of these stuff will overflow. + * that none of this stuff will overflow. */ const png_uint_32 tag_count = png_get_uint_32( profile_header+128); @@ -1564,19 +1584,11 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) return; } } - - else if (size > 0) - errmsg = "truncated"; - -#ifndef __COVERITY__ - else + if (errmsg == NULL) errmsg = png_ptr->zstream.msg; -#endif } - /* else png_icc_check_tag_table output an error */ } - else /* profile truncated */ errmsg = png_ptr->zstream.msg; } @@ -1717,13 +1729,13 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) data_length = length - (png_uint_32)(entry_start - buffer); /* Integrity-check the data length */ - if ((data_length % entry_size) != 0) + if ((data_length % (unsigned int)entry_size) != 0) { png_warning(png_ptr, "sPLT chunk has bad length"); return; } - dl = (png_int_32)(data_length / entry_size); + dl = (png_uint_32)(data_length / (unsigned int)entry_size); max_dl = PNG_SIZE_MAX / (sizeof (png_sPLT_entry)); if (dl > max_dl) @@ -1732,10 +1744,10 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) return; } - new_palette.nentries = (png_int_32)(data_length / entry_size); + new_palette.nentries = (png_int_32)(data_length / (unsigned int)entry_size); - new_palette.entries = (png_sPLT_entryp)png_malloc_warn( - png_ptr, new_palette.nentries * (sizeof (png_sPLT_entry))); + new_palette.entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, + (png_alloc_size_t) new_palette.nentries * (sizeof (png_sPLT_entry))); if (new_palette.entries == NULL) { @@ -2005,6 +2017,69 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } #endif +#ifdef PNG_READ_eXIf_SUPPORTED +void /* PRIVATE */ +png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +{ + unsigned int i; + + png_debug(1, "in png_handle_eXIf"); + + if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) + png_chunk_error(png_ptr, "missing IHDR"); + + if (length < 2) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too short"); + return; + } + + else if (info_ptr == NULL || (info_ptr->valid & PNG_INFO_eXIf) != 0) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "duplicate"); + return; + } + + info_ptr->free_me |= PNG_FREE_EXIF; + + info_ptr->eXIf_buf = png_voidcast(png_bytep, + png_malloc_warn(png_ptr, length)); + + if (info_ptr->eXIf_buf == NULL) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of memory"); + return; + } + + for (i = 0; i < length; i++) + { + png_byte buf[1]; + png_crc_read(png_ptr, buf, 1); + info_ptr->eXIf_buf[i] = buf[0]; + if (i == 1 && buf[0] != 'M' && buf[0] != 'I' + && info_ptr->eXIf_buf[0] != buf[0]) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "incorrect byte-order specifier"); + png_free(png_ptr, info_ptr->eXIf_buf); + info_ptr->eXIf_buf = NULL; + return; + } + } + + if (png_crc_finish(png_ptr, 0) != 0) + return; + + png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf); + + png_free(png_ptr, info_ptr->eXIf_buf); + info_ptr->eXIf_buf = NULL; +} +#endif + #ifdef PNG_READ_hIST_SUPPORTED void /* PRIVATE */ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) @@ -2533,6 +2608,9 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) png_ptr->mode |= PNG_AFTER_IDAT; + /* Note, "length" is sufficient here; we won't be adding + * a null terminator later. + */ buffer = png_read_buffer(png_ptr, length, 2/*silent*/); if (buffer == NULL) @@ -2579,23 +2657,28 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_text text; - /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except - * for the extra compression type byte and the fact that it isn't - * necessarily '\0' terminated. - */ - buffer = png_ptr->read_buffer; - buffer[uncompressed_length+(keyword_length+2)] = 0; + if (png_ptr->read_buffer == NULL) + errmsg="Read failure in png_handle_zTXt"; + else + { + /* It worked; png_ptr->read_buffer now looks like a tEXt chunk + * except for the extra compression type byte and the fact that + * it isn't necessarily '\0' terminated. + */ + buffer = png_ptr->read_buffer; + buffer[uncompressed_length+(keyword_length+2)] = 0; - text.compression = PNG_TEXT_COMPRESSION_zTXt; - text.key = (png_charp)buffer; - text.text = (png_charp)(buffer + keyword_length+2); - text.text_length = uncompressed_length; - text.itxt_length = 0; - text.lang = NULL; - text.lang_key = NULL; + text.compression = PNG_TEXT_COMPRESSION_zTXt; + text.key = (png_charp)buffer; + text.text = (png_charp)(buffer + keyword_length+2); + text.text_length = uncompressed_length; + text.itxt_length = 0; + text.lang = NULL; + text.lang_key = NULL; - if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0) - errmsg = "insufficient memory"; + if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0) + errmsg = "insufficient memory"; + } } else @@ -2971,7 +3054,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, case 2: png_ptr->user_chunk_cache_max = 1; png_chunk_benign_error(png_ptr, "no space in chunk cache"); - /* FALL THROUGH */ + /* FALLTHROUGH */ case 1: /* NOTE: prior to 1.6.0 this case resulted in an unknown critical * chunk being skipped, now there will be a hard error below. @@ -2980,7 +3063,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, default: /* not at limit */ --(png_ptr->user_chunk_cache_max); - /* FALL THROUGH */ + /* FALLTHROUGH */ case 0: /* no limit */ # endif /* USER_LIMITS */ /* Here when the limit isn't reached or when limits are compiled @@ -3031,20 +3114,58 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, */ void /* PRIVATE */ -png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name) +png_check_chunk_name(png_const_structrp png_ptr, const png_uint_32 chunk_name) { int i; + png_uint_32 cn=chunk_name; png_debug(1, "in png_check_chunk_name"); for (i=1; i<=4; ++i) { - int c = chunk_name & 0xff; + int c = cn & 0xff; if (c < 65 || c > 122 || (c > 90 && c < 97)) png_chunk_error(png_ptr, "invalid chunk type"); - chunk_name >>= 8; + cn >>= 8; + } +} + +void /* PRIVATE */ +png_check_chunk_length(png_const_structrp png_ptr, const png_uint_32 length) +{ + png_alloc_size_t limit = PNG_UINT_31_MAX; + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < limit) + limit = png_ptr->user_chunk_malloc_max; +# elif PNG_USER_CHUNK_MALLOC_MAX > 0 + if (PNG_USER_CHUNK_MALLOC_MAX < limit) + limit = PNG_USER_CHUNK_MALLOC_MAX; +# endif + if (png_ptr->chunk_name == png_IDAT) + { + png_alloc_size_t idat_limit = PNG_UINT_31_MAX; + size_t row_factor = + (png_ptr->width * png_ptr->channels * (png_ptr->bit_depth > 8? 2: 1) + + 1 + (png_ptr->interlaced? 6: 0)); + if (png_ptr->height > PNG_UINT_32_MAX/row_factor) + idat_limit=PNG_UINT_31_MAX; + else + idat_limit = png_ptr->height * row_factor; + row_factor = row_factor > 32566? 32566 : row_factor; + idat_limit += 6 + 5*(idat_limit/row_factor+1); /* zlib+deflate overhead */ + idat_limit=idat_limit < PNG_UINT_31_MAX? idat_limit : PNG_UINT_31_MAX; + limit = limit < idat_limit? idat_limit : limit; + } + + if (length > limit) + { + png_debug2(0," length = %lu, limit = %lu", + (unsigned long)length,(unsigned long)limit); + png_chunk_error(png_ptr, "chunk data is too large"); } } @@ -3099,7 +3220,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) # ifdef PNG_READ_PACKSWAP_SUPPORTED if ((png_ptr->transformations & PNG_PACKSWAP) != 0) /* little-endian byte */ - end_mask = 0xff << end_mask; + end_mask = (unsigned int)(0xff << end_mask); else /* big-endian byte */ # endif @@ -3373,7 +3494,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) */ do { - dp[0] = sp[0], dp[1] = sp[1]; + dp[0] = sp[0]; dp[1] = sp[1]; if (row_width <= bytes_to_jump) return; @@ -3394,7 +3515,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) */ for (;;) { - dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2]; + dp[0] = sp[0]; dp[1] = sp[1]; dp[2] = sp[2]; if (row_width <= bytes_to_jump) return; @@ -3545,7 +3666,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, { /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Offset to next interlace block */ - static PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + static PNG_CONST unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; png_debug(1, "in png_do_read_interlace"); if (row != NULL && row_info != NULL) @@ -3560,9 +3681,10 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, { png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; + unsigned int sshift, dshift; + unsigned int s_start, s_end; + int s_inc; + int jstop = (int)png_pass_inc[pass]; png_byte v; png_uint_32 i; int j; @@ -3570,8 +3692,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, #ifdef PNG_READ_PACKSWAP_SUPPORTED if ((transformations & PNG_PACKSWAP) != 0) { - sshift = (int)((row_info->width + 7) & 0x07); - dshift = (int)((final_width + 7) & 0x07); + sshift = ((row_info->width + 7) & 0x07); + dshift = ((final_width + 7) & 0x07); s_start = 7; s_end = 0; s_inc = -1; @@ -3580,8 +3702,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, else #endif { - sshift = 7 - (int)((row_info->width + 7) & 0x07); - dshift = 7 - (int)((final_width + 7) & 0x07); + sshift = 7 - ((row_info->width + 7) & 0x07); + dshift = 7 - ((final_width + 7) & 0x07); s_start = 0; s_end = 7; s_inc = 1; @@ -3593,7 +3715,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, for (j = 0; j < jstop; j++) { unsigned int tmp = *dp & (0x7f7f >> (7 - dshift)); - tmp |= v << dshift; + tmp |= (unsigned int)(v << dshift); *dp = (png_byte)(tmp & 0xff); if (dshift == s_end) @@ -3603,7 +3725,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - dshift += s_inc; + dshift = (unsigned int)((int)dshift + s_inc); } if (sshift == s_end) @@ -3613,7 +3735,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - sshift += s_inc; + sshift = (unsigned int)((int)sshift + s_inc); } break; } @@ -3622,16 +3744,17 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, { png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); - int sshift, dshift; - int s_start, s_end, s_inc; - int jstop = png_pass_inc[pass]; + unsigned int sshift, dshift; + unsigned int s_start, s_end; + int s_inc; + int jstop = (int)png_pass_inc[pass]; png_uint_32 i; #ifdef PNG_READ_PACKSWAP_SUPPORTED if ((transformations & PNG_PACKSWAP) != 0) { - sshift = (int)(((row_info->width + 3) & 0x03) << 1); - dshift = (int)(((final_width + 3) & 0x03) << 1); + sshift = (((row_info->width + 3) & 0x03) << 1); + dshift = (((final_width + 3) & 0x03) << 1); s_start = 6; s_end = 0; s_inc = -2; @@ -3640,8 +3763,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, else #endif { - sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); - dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + sshift = ((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = ((3 - ((final_width + 3) & 0x03)) << 1); s_start = 0; s_end = 6; s_inc = 2; @@ -3656,7 +3779,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, for (j = 0; j < jstop; j++) { unsigned int tmp = *dp & (0x3f3f >> (6 - dshift)); - tmp |= v << dshift; + tmp |= (unsigned int)(v << dshift); *dp = (png_byte)(tmp & 0xff); if (dshift == s_end) @@ -3666,7 +3789,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - dshift += s_inc; + dshift = (unsigned int)((int)dshift + s_inc); } if (sshift == s_end) @@ -3676,7 +3799,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - sshift += s_inc; + sshift = (unsigned int)((int)sshift + s_inc); } break; } @@ -3685,16 +3808,17 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, { png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); - int sshift, dshift; - int s_start, s_end, s_inc; + unsigned int sshift, dshift; + unsigned int s_start, s_end; + int s_inc; png_uint_32 i; - int jstop = png_pass_inc[pass]; + int jstop = (int)png_pass_inc[pass]; #ifdef PNG_READ_PACKSWAP_SUPPORTED if ((transformations & PNG_PACKSWAP) != 0) { - sshift = (int)(((row_info->width + 1) & 0x01) << 2); - dshift = (int)(((final_width + 1) & 0x01) << 2); + sshift = (((row_info->width + 1) & 0x01) << 2); + dshift = (((final_width + 1) & 0x01) << 2); s_start = 4; s_end = 0; s_inc = -4; @@ -3703,8 +3827,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, else #endif { - sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); - dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + sshift = ((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = ((1 - ((final_width + 1) & 0x01)) << 2); s_start = 0; s_end = 4; s_inc = 4; @@ -3718,7 +3842,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, for (j = 0; j < jstop; j++) { unsigned int tmp = *dp & (0xf0f >> (4 - dshift)); - tmp |= v << dshift; + tmp |= (unsigned int)(v << dshift); *dp = (png_byte)(tmp & 0xff); if (dshift == s_end) @@ -3728,7 +3852,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - dshift += s_inc; + dshift = (unsigned int)((int)dshift + s_inc); } if (sshift == s_end) @@ -3738,7 +3862,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } else - sshift += s_inc; + sshift = (unsigned int)((int)sshift + s_inc); } break; } @@ -3752,7 +3876,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; - int jstop = png_pass_inc[pass]; + int jstop = (int)png_pass_inc[pass]; png_uint_32 i; for (i = 0; i < row_info->width; i++) @@ -3880,7 +4004,10 @@ png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, /* Find the best predictor, the least of pa, pb, pc favoring the earlier * ones in the case of a tie. */ - if (pb < pa) pa = pb, a = b; + if (pb < pa) + { + pa = pb; a = b; + } if (pc < pa) a = c; /* Calculate the current pixel in a, and move the previous row pixel to c @@ -3896,7 +4023,7 @@ static void png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, png_const_bytep prev_row) { - int bpp = (row_info->pixel_depth + 7) >> 3; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; png_bytep rp_end = row + bpp; /* Process the first pixel in the row completely (this is the same as 'up' @@ -3909,7 +4036,7 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, } /* Remainder */ - rp_end += row_info->rowbytes - bpp; + rp_end = rp_end + (row_info->rowbytes - bpp); while (row < rp_end) { @@ -3932,7 +4059,10 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, pc = (p + pc) < 0 ? -(p + pc) : p + pc; #endif - if (pb < pa) pa = pb, a = b; + if (pb < pa) + { + pa = pb; a = b; + } if (pc < pa) a = c; a += *row; @@ -4254,7 +4384,7 @@ png_read_start_row(png_structrp png_ptr) /* Offset to next interlace block in the y direction */ static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; - int max_pixel_depth; + unsigned int max_pixel_depth; png_size_t row_bytes; png_debug(1, "in png_read_start_row"); @@ -4283,7 +4413,7 @@ png_read_start_row(png_structrp png_ptr) png_ptr->iwidth = png_ptr->width; } - max_pixel_depth = png_ptr->pixel_depth; + max_pixel_depth = (unsigned int)png_ptr->pixel_depth; /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpler set of * calculations to calculate the final pixel depth, then @@ -4418,7 +4548,7 @@ png_read_start_row(png_structrp png_ptr) defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0) { - int user_pixel_depth = png_ptr->user_transform_depth * + unsigned int user_pixel_depth = png_ptr->user_transform_depth * png_ptr->user_transform_channels; if (user_pixel_depth > max_pixel_depth) @@ -4440,7 +4570,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) * for safety's sake */ row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + - 1 + ((max_pixel_depth + 7) >> 3); + 1 + ((max_pixel_depth + 7) >> 3U); #ifdef PNG_MAX_MALLOC_64K if (row_bytes > (png_uint_32)65536L) @@ -4509,7 +4639,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) * does not, so free the read buffer now regardless; the sequential reader * reallocates it on demand. */ - if (png_ptr->read_buffer != 0) + if (png_ptr->read_buffer != NULL) { png_bytep buffer = png_ptr->read_buffer; diff --git a/3rdparty/libpng/pngset.c b/3rdparty/libpng/pngset.c index cccd9cdc7e..6f3a1ee11e 100644 --- a/3rdparty/libpng/pngset.c +++ b/3rdparty/libpng/pngset.c @@ -1,8 +1,8 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.32 [August 24, 2017] + * Copyright (c) 1998-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -134,6 +134,53 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, #endif /* cHRM */ +#ifdef PNG_eXIf_SUPPORTED +void PNGAPI +png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr, + const png_bytep eXIf_buf) +{ + png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1"); + PNG_UNUSED(info_ptr) + PNG_UNUSED(eXIf_buf) +} + +void PNGAPI +png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr, + const png_uint_32 num_exif, const png_bytep eXIf_buf) +{ + int i; + + png_debug1(1, "in %s storage function", "eXIf"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->exif) + { + png_free(png_ptr, info_ptr->exif); + info_ptr->exif = NULL; + } + + info_ptr->num_exif = num_exif; + + info_ptr->exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr, + info_ptr->num_exif)); + + if (info_ptr->exif == NULL) + { + png_warning(png_ptr, "Insufficient memory for eXIf chunk data"); + return; + } + + info_ptr->free_me |= PNG_FREE_EXIF; + + for (i = 0; i < (int) info_ptr->num_exif; i++) + info_ptr->exif[i] = eXIf_buf[i]; + + info_ptr->valid |= PNG_INFO_eXIf; +} +#endif /* eXIf */ + #ifdef PNG_gAMA_SUPPORTED void PNGFAPI png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr, @@ -283,17 +330,29 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, /* Check that the type matches the specification. */ if (type < 0 || type > 3) - png_error(png_ptr, "Invalid pCAL equation type"); + { + png_chunk_report(png_ptr, "Invalid pCAL equation type", + PNG_CHUNK_WRITE_ERROR); + return; + } if (nparams < 0 || nparams > 255) - png_error(png_ptr, "Invalid pCAL parameter count"); + { + png_chunk_report(png_ptr, "Invalid pCAL parameter count", + PNG_CHUNK_WRITE_ERROR); + return; + } /* Validate params[nparams] */ for (i=0; ipcal_purpose = png_voidcast(png_charp, @@ -301,8 +360,8 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, if (info_ptr->pcal_purpose == NULL) { - png_warning(png_ptr, "Insufficient memory for pCAL purpose"); - + png_chunk_report(png_ptr, "Insufficient memory for pCAL purpose", + PNG_CHUNK_WRITE_ERROR); return; } @@ -331,7 +390,7 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, memcpy(info_ptr->pcal_units, units, length); info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, - (png_size_t)((nparams + 1) * (sizeof (png_charp))))); + (png_size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp))))); if (info_ptr->pcal_params == NULL) { @@ -340,7 +399,8 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, return; } - memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp))); + memset(info_ptr->pcal_params, 0, ((unsigned int)nparams + 1) * + (sizeof (png_charp))); for (i = 0; i < nparams; i++) { @@ -563,7 +623,8 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)))); if (num_palette > 0) - memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color))); + memcpy(png_ptr->palette, palette, (unsigned int)num_palette * + (sizeof (png_color))); info_ptr->palette = png_ptr->palette; info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; @@ -1080,7 +1141,7 @@ png_set_sPLT(png_const_structrp png_ptr, * checked it when doing the allocation. */ memcpy(np->entries, entries->entries, - entries->nentries * sizeof (png_sPLT_entry)); + (unsigned int)entries->nentries * sizeof (png_sPLT_entry)); /* Note that 'continue' skips the advance of the out pointer and out * count, so an invalid entry is not added. @@ -1088,8 +1149,9 @@ png_set_sPLT(png_const_structrp png_ptr, info_ptr->valid |= PNG_INFO_sPLT; ++(info_ptr->splt_palettes_num); ++np; + ++entries; } - while (++entries, --nentries); + while (--nentries); if (nentries > 0) png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR); @@ -1249,7 +1311,7 @@ png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr, { png_app_error(png_ptr, "invalid unknown chunk location"); /* Fake out the pre 1.6.0 behavior: */ - if ((location & PNG_HAVE_IDAT) != 0) /* undocumented! */ + if (((unsigned int)location & PNG_HAVE_IDAT) != 0) /* undocumented! */ location = PNG_AFTER_IDAT; else @@ -1340,6 +1402,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, static PNG_CONST png_byte chunks_to_ignore[] = { 98, 75, 71, 68, '\0', /* bKGD */ 99, 72, 82, 77, '\0', /* cHRM */ + 101, 88, 73, 102, '\0', /* eXIf */ 103, 65, 77, 65, '\0', /* gAMA */ 104, 73, 83, 84, '\0', /* hIST */ 105, 67, 67, 80, '\0', /* iCCP */ @@ -1373,7 +1436,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, return; } - num_chunks = num_chunks_in; + num_chunks = (unsigned int)num_chunks_in; } old_num_chunks = png_ptr->num_chunk_list; @@ -1563,7 +1626,7 @@ void PNGAPI png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask) { if (png_ptr != NULL && info_ptr != NULL) - info_ptr->valid &= ~mask; + info_ptr->valid &= (unsigned int)(~mask); } @@ -1682,14 +1745,16 @@ png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) png_byte ch = (png_byte)*key++; if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/)) - *new_key++ = ch, ++key_len, space = 0; + { + *new_key++ = ch; ++key_len; space = 0; + } else if (space == 0) { /* A space or an invalid character when one wasn't seen immediately * before; output just a space. */ - *new_key++ = 32, ++key_len, space = 1; + *new_key++ = 32; ++key_len; space = 1; /* If the character was not a space then it is invalid. */ if (ch != 32) @@ -1702,7 +1767,7 @@ png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) if (key_len > 0 && space != 0) /* trailing space */ { - --key_len, --new_key; + --key_len; --new_key; if (bad_character == 0) bad_character = 32; } diff --git a/3rdparty/libpng/pngstruct.h b/3rdparty/libpng/pngstruct.h index 2b0eb49025..d83f971253 100644 --- a/3rdparty/libpng/pngstruct.h +++ b/3rdparty/libpng/pngstruct.h @@ -1,8 +1,8 @@ /* pngstruct.h - header file for PNG reference library * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.32 [August 24, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -263,7 +263,7 @@ struct png_struct_def /* pixel depth used for the row buffers */ png_byte transformed_pixel_depth; /* pixel depth after read/write transforms */ -#if PNG_ZLIB_VERNUM >= 0x1240 +#if ZLIB_VERNUM >= 0x1240 png_byte zstream_start; /* at start of an input zlib stream */ #endif /* Zlib >= 1.2.4 */ #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) @@ -353,7 +353,7 @@ struct png_struct_def /* Options */ #ifdef PNG_SET_OPTION_SUPPORTED - png_byte options; /* On/off state (up to 4 options) */ + png_uint_32 options; /* On/off state (up to 16 options) */ #endif #if PNG_LIBPNG_VER < 10700 diff --git a/3rdparty/libpng/pngtrans.c b/3rdparty/libpng/pngtrans.c index e5cbd79b9d..6882f0fd7b 100644 --- a/3rdparty/libpng/pngtrans.c +++ b/3rdparty/libpng/pngtrans.c @@ -1,8 +1,8 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.33 [September 28, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -514,11 +514,15 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ ++sp; else /* Skip initial channel and, for sp, the filler */ - sp += 2, ++dp; + { + sp += 2; ++dp; + } /* For a 1 pixel wide image there is nothing to do */ while (sp < ep) - *dp++ = *sp, sp += 2; + { + *dp++ = *sp; sp += 2; + } row_info->pixel_depth = 8; } @@ -528,10 +532,14 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ sp += 2; else /* Skip initial channel and, for sp, the filler */ - sp += 4, dp += 2; + { + sp += 4; dp += 2; + } while (sp < ep) - *dp++ = *sp++, *dp++ = *sp, sp += 3; + { + *dp++ = *sp++; *dp++ = *sp; sp += 3; + } row_info->pixel_depth = 16; } @@ -554,11 +562,15 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ ++sp; else /* Skip initial channels and, for sp, the filler */ - sp += 4, dp += 3; + { + sp += 4; dp += 3; + } /* Note that the loop adds 3 to dp and 4 to sp each time. */ while (sp < ep) - *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2; + { + *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp; sp += 2; + } row_info->pixel_depth = 24; } @@ -568,14 +580,16 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ sp += 2; else /* Skip initial channels and, for sp, the filler */ - sp += 8, dp += 6; + { + sp += 8; dp += 6; + } while (sp < ep) { /* Copy 6 bytes, skip 2 */ - *dp++ = *sp++, *dp++ = *sp++; - *dp++ = *sp++, *dp++ = *sp++; - *dp++ = *sp++, *dp++ = *sp, sp += 3; + *dp++ = *sp++; *dp++ = *sp++; + *dp++ = *sp++; *dp++ = *sp++; + *dp++ = *sp++; *dp++ = *sp; sp += 3; } row_info->pixel_depth = 48; @@ -595,7 +609,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) return; /* The filler channel has gone already */ /* Fix the rowbytes value. */ - row_info->rowbytes = dp-row; + row_info->rowbytes = (png_size_t)(dp-row); } #endif @@ -693,8 +707,8 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) * and this calculation is used because it avoids warnings that other * forms produced on either GCC or MSVC. */ - int padding = (-row_info->pixel_depth * row_info->width) & 7; - png_bytep rp = png_ptr->row_buf + row_info->rowbytes; + int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width); + png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1; switch (row_info->bit_depth) { diff --git a/3rdparty/libpng/pngwrite.c b/3rdparty/libpng/pngwrite.c index aaa2b017df..a16d77ce00 100644 --- a/3rdparty/libpng/pngwrite.c +++ b/3rdparty/libpng/pngwrite.c @@ -1,8 +1,8 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.32 [August 24, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -237,6 +237,11 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); #endif +#ifdef PNG_WRITE_eXIf_SUPPORTED + if ((info_ptr->valid & PNG_INFO_eXIf) != 0) + png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif); +#endif + #ifdef PNG_WRITE_hIST_SUPPORTED if ((info_ptr->valid & PNG_INFO_hIST) != 0) png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); @@ -432,6 +437,12 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) } } #endif + +#ifdef PNG_WRITE_eXIf_SUPPORTED + if ((info_ptr->valid & PNG_INFO_eXIf) != 0) + png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif); +#endif + #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT); #endif @@ -666,9 +677,9 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) { - png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); - png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); - png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 s0 = (png_uint_32)(*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5); png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); *(rp ) = (png_byte)(red >> 8); @@ -901,7 +912,7 @@ png_set_flush(png_structrp png_ptr, int nrows) if (png_ptr == NULL) return; - png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); + png_ptr->flush_dist = (nrows < 0 ? 0 : (png_uint_32)nrows); } /* Flush the current output buffers now */ @@ -1007,8 +1018,8 @@ png_set_filter(png_structrp png_ptr, int method, int filters) case 5: case 6: case 7: png_app_error(png_ptr, "Unknown row filter for method 0"); - /* FALL THROUGH */ #endif /* WRITE_FILTER */ + /* FALLTHROUGH */ case PNG_FILTER_VALUE_NONE: png_ptr->do_filter = PNG_FILTER_NONE; break; @@ -1525,7 +1536,8 @@ png_write_image_16bit(png_voidp argument) display->first_row); png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); png_uint_16p row_end; - const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; + const unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? + 3 : 1; int aindex = 0; png_uint_32 y = image->height; @@ -1539,9 +1551,9 @@ png_write_image_16bit(png_voidp argument) ++output_row; } else - aindex = channels; + aindex = (int)channels; # else - aindex = channels; + aindex = (int)channels; # endif } @@ -1554,7 +1566,7 @@ png_write_image_16bit(png_voidp argument) */ row_end = output_row + image->width * (channels+1); - while (y-- > 0) + for (; y > 0; --y) { png_const_uint_16p in_ptr = input_row; png_uint_16p out_ptr = output_row; @@ -1575,7 +1587,7 @@ png_write_image_16bit(png_voidp argument) if (alpha > 0 && alpha < 65535) reciprocal = ((0xffff<<15)+(alpha>>1))/alpha; - c = channels; + c = (int)channels; do /* always at least one channel */ { png_uint_16 component = *in_ptr++; @@ -1610,7 +1622,7 @@ png_write_image_16bit(png_voidp argument) } png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); - input_row += display->row_bytes/(sizeof (png_uint_16)); + input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16)); } return 1; @@ -1683,7 +1695,8 @@ png_write_image_8bit(png_voidp argument) display->first_row); png_bytep output_row = png_voidcast(png_bytep, display->local_row); png_uint_32 y = image->height; - const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; + const unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? + 3 : 1; if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0) { @@ -1700,12 +1713,12 @@ png_write_image_8bit(png_voidp argument) else # endif - aindex = channels; + aindex = (int)channels; /* Use row_end in place of a loop counter: */ row_end = output_row + image->width * (channels+1); - while (y-- > 0) + for (; y > 0; --y) { png_const_uint_16p in_ptr = input_row; png_bytep out_ptr = output_row; @@ -1723,7 +1736,7 @@ png_write_image_8bit(png_voidp argument) if (alphabyte > 0 && alphabyte < 255) reciprocal = UNP_RECIPROCAL(alpha); - c = channels; + c = (int)channels; do /* always at least one channel */ *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal); while (--c > 0); @@ -1735,7 +1748,7 @@ png_write_image_8bit(png_voidp argument) png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); - input_row += display->row_bytes/(sizeof (png_uint_16)); + input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16)); } /* while y */ } @@ -1746,7 +1759,7 @@ png_write_image_8bit(png_voidp argument) */ png_bytep row_end = output_row + image->width * channels; - while (y-- > 0) + for (; y > 0; --y) { png_const_uint_16p in_ptr = input_row; png_bytep out_ptr = output_row; @@ -1760,7 +1773,7 @@ png_write_image_8bit(png_voidp argument) } png_write_row(png_ptr, output_row); - input_row += display->row_bytes/(sizeof (png_uint_16)); + input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16)); } } @@ -1777,7 +1790,7 @@ png_image_set_PLTE(png_image_write_control *display) /* NOTE: the caller must check for cmap != NULL and entries != 0 */ const png_uint_32 format = image->format; - const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); + const unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); # if defined(PNG_FORMAT_BGR_SUPPORTED) &&\ defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED) @@ -1809,7 +1822,7 @@ png_image_set_PLTE(png_image_write_control *display) { png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap); - entry += i * channels; + entry += (unsigned int)i * channels; if ((channels & 1) != 0) /* no alpha */ { @@ -1865,7 +1878,7 @@ png_image_set_PLTE(png_image_write_control *display) { png_const_bytep entry = png_voidcast(png_const_bytep, cmap); - entry += i * channels; + entry += (unsigned int)i * channels; switch (channels) { @@ -1873,7 +1886,7 @@ png_image_set_PLTE(png_image_write_control *display) tRNS[i] = entry[afirst ? 0 : 3]; if (tRNS[i] < 255) num_trans = i+1; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 3: palette[i].blue = entry[afirst + (2 ^ bgr)]; palette[i].green = entry[afirst + 1]; @@ -1884,7 +1897,7 @@ png_image_set_PLTE(png_image_write_control *display) tRNS[i] = entry[1 ^ afirst]; if (tRNS[i] < 255) num_trans = i+1; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 1: palette[i].blue = palette[i].red = palette[i].green = entry[afirst]; @@ -1910,7 +1923,7 @@ png_image_set_PLTE(png_image_write_control *display) png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS, num_trans, NULL); - image->colormap_entries = entries; + image->colormap_entries = (png_uint_32)entries; } static int @@ -1927,7 +1940,7 @@ png_image_write_main(png_voidp argument) int colormap = (format & PNG_FORMAT_FLAG_COLORMAP); int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */ int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA); - int write_16bit = linear && !colormap && (display->convert_to_8bit == 0); + int write_16bit = linear && (display->convert_to_8bit == 0); # ifdef PNG_BENIGN_ERRORS_SUPPORTED /* Make sure we error out on any bad situation */ @@ -1940,7 +1953,7 @@ png_image_write_main(png_voidp argument) { const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); - if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */ + if (image->width <= 0x7fffffffU/channels) /* no overflow */ { png_uint_32 check; const png_uint_32 png_row_stride = image->width * channels; @@ -1949,10 +1962,10 @@ png_image_write_main(png_voidp argument) display->row_stride = (png_int_32)/*SAFE*/png_row_stride; if (display->row_stride < 0) - check = -display->row_stride; + check = (png_uint_32)(-display->row_stride); else - check = display->row_stride; + check = (png_uint_32)display->row_stride; if (check >= png_row_stride) { @@ -1960,7 +1973,7 @@ png_image_write_main(png_voidp argument) * limits the whole image size to 32 bits for API compatibility with * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro. */ - if (image->height > 0xFFFFFFFF/png_row_stride) + if (image->height > 0xffffffffU/png_row_stride) png_error(image->opaque->png_ptr, "memory image too large"); } @@ -2136,7 +2149,7 @@ png_image_write_main(png_voidp argument) ptrdiff_t row_bytes = display->row_bytes; png_uint_32 y = image->height; - while (y-- > 0) + for (; y > 0; --y) { png_write_row(png_ptr, row); row += row_bytes; diff --git a/3rdparty/libpng/pngwtran.c b/3rdparty/libpng/pngwtran.c index 423fb2d5bb..377b43e5ca 100644 --- a/3rdparty/libpng/pngwtran.c +++ b/3rdparty/libpng/pngwtran.c @@ -1,7 +1,7 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.6.24 [August 4, 2016] + * Last changed in libpng 1.6.26 [October 20, 2016] * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -177,7 +177,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) { int shift_start[4], shift_dec[4]; - int channels = 0; + unsigned int channels = 0; if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) { diff --git a/3rdparty/libpng/pngwutil.c b/3rdparty/libpng/pngwutil.c index 3f1ed0cc8f..0d4fb1336c 100644 --- a/3rdparty/libpng/pngwutil.c +++ b/3rdparty/libpng/pngwutil.c @@ -1,8 +1,8 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson + * Last changed in libpng 1.6.32 [August 24, 2017] + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -408,7 +408,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, png_ptr->zstream.avail_out = 0; /* Now initialize if required, setting the new parameters, otherwise just - * to a simple reset to the previous parameters. + * do a simple reset to the previous parameters. */ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0) ret = deflateReset(&png_ptr->zstream); @@ -675,6 +675,7 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, int interlace_type) { png_byte buf[13]; /* Buffer to store the IHDR info */ + int is_invalid_depth; png_debug(1, "in png_write_IHDR"); @@ -700,11 +701,11 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, break; case PNG_COLOR_TYPE_RGB: + is_invalid_depth = (bit_depth != 8); #ifdef PNG_WRITE_16BIT_SUPPORTED - if (bit_depth != 8 && bit_depth != 16) -#else - if (bit_depth != 8) + is_invalid_depth = (is_invalid_depth && bit_depth != 16); #endif + if (is_invalid_depth) png_error(png_ptr, "Invalid bit depth for RGB image"); png_ptr->channels = 3; @@ -726,18 +727,22 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, break; case PNG_COLOR_TYPE_GRAY_ALPHA: - if (bit_depth != 8 && bit_depth != 16) + is_invalid_depth = (bit_depth != 8); +#ifdef PNG_WRITE_16BIT_SUPPORTED + is_invalid_depth = (is_invalid_depth && bit_depth != 16); +#endif + if (is_invalid_depth) png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); png_ptr->channels = 2; break; case PNG_COLOR_TYPE_RGB_ALPHA: + is_invalid_depth = (bit_depth != 8); #ifdef PNG_WRITE_16BIT_SUPPORTED - if (bit_depth != 8 && bit_depth != 16) -#else - if (bit_depth != 8) + is_invalid_depth = (is_invalid_depth && bit_depth != 16); #endif + if (is_invalid_depth) png_error(png_ptr, "Invalid bit depth for RGBA image"); png_ptr->channels = 4; @@ -998,7 +1003,8 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, optimize_cmf(data, png_image_size(png_ptr)); #endif - png_write_complete_chunk(png_ptr, png_IDAT, data, size); + if (size > 0) + png_write_complete_chunk(png_ptr, png_IDAT, data, size); png_ptr->mode |= PNG_HAVE_IDAT; png_ptr->zstream.next_out = data; @@ -1044,7 +1050,8 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, optimize_cmf(data, png_image_size(png_ptr)); #endif - png_write_complete_chunk(png_ptr, png_IDAT, data, size); + if (size > 0) + png_write_complete_chunk(png_ptr, png_IDAT, data, size); png_ptr->zstream.avail_out = 0; png_ptr->zstream.next_out = NULL; png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT; @@ -1176,7 +1183,7 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) png_byte new_name[80]; png_byte entrybuf[10]; png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); - png_size_t palette_size = entry_size * spalette->nentries; + png_size_t palette_size = entry_size * (png_size_t)spalette->nentries; png_sPLT_entryp ep; #ifndef PNG_POINTER_INDEXING_SUPPORTED int i; @@ -1466,6 +1473,28 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) } #endif +#ifdef PNG_WRITE_eXIf_SUPPORTED +/* Write the Exif data */ +void /* PRIVATE */ +png_write_eXIf(png_structrp png_ptr, png_bytep exif, int num_exif) +{ + int i; + png_byte buf[1]; + + png_debug(1, "in png_write_eXIf"); + + png_write_chunk_header(png_ptr, png_eXIf, (png_uint_32)(num_exif)); + + for (i = 0; i < num_exif; i++) + { + buf[0] = exif[i]; + png_write_chunk_data(png_ptr, buf, (png_size_t)1); + } + + png_write_chunk_end(png_ptr); +} +#endif + #ifdef PNG_WRITE_hIST_SUPPORTED /* Write the histogram */ void /* PRIVATE */ @@ -1743,7 +1772,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, total_len = purpose_len + units_len + 10; params_len = (png_size_tp)png_malloc(png_ptr, - (png_alloc_size_t)(nparams * (sizeof (png_size_t)))); + (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (png_size_t)))); /* Find the length of each parameter, making sure we don't count the * null terminator for the last parameter. @@ -2255,7 +2284,7 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, png_bytep rp, dp, lp; png_size_t i; png_size_t sum = 0; - int v; + unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; @@ -2264,7 +2293,7 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, { v = *dp = *rp; #ifdef PNG_USE_ABS - sum += 128 - abs(v - 128); + sum += 128 - abs((int)v - 128); #else sum += (v < 128) ? v : 256 - v; #endif @@ -2275,7 +2304,7 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, { v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); #ifdef PNG_USE_ABS - sum += 128 - abs(v - 128); + sum += 128 - abs((int)v - 128); #else sum += (v < 128) ? v : 256 - v; #endif @@ -2316,7 +2345,7 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, png_bytep rp, dp, pp; png_size_t i; png_size_t sum = 0; - int v; + unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; @@ -2326,7 +2355,7 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, { v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); #ifdef PNG_USE_ABS - sum += 128 - abs(v - 128); + sum += 128 - abs((int)v - 128); #else sum += (v < 128) ? v : 256 - v; #endif @@ -2360,7 +2389,7 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, png_bytep rp, dp, pp, lp; png_uint_32 i; png_size_t sum = 0; - int v; + unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; @@ -2370,7 +2399,7 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); #ifdef PNG_USE_ABS - sum += 128 - abs(v - 128); + sum += 128 - abs((int)v - 128); #else sum += (v < 128) ? v : 256 - v; #endif @@ -2382,7 +2411,7 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, & 0xff); #ifdef PNG_USE_ABS - sum += 128 - abs(v - 128); + sum += 128 - abs((int)v - 128); #else sum += (v < 128) ? v : 256 - v; #endif @@ -2422,7 +2451,7 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, png_bytep rp, dp, pp, cp, lp; png_size_t i; png_size_t sum = 0; - int v; + unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; @@ -2432,7 +2461,7 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); #ifdef PNG_USE_ABS - sum += 128 - abs(v - 128); + sum += 128 - abs((int)v - 128); #else sum += (v < 128) ? v : 256 - v; #endif @@ -2465,7 +2494,7 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); #ifdef PNG_USE_ABS - sum += 128 - abs(v - 128); + sum += 128 - abs((int)v - 128); #else sum += (v < 128) ? v : 256 - v; #endif @@ -2588,14 +2617,14 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) png_bytep rp; png_size_t sum = 0; png_size_t i; - int v; + unsigned int v; { for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) { v = *rp; #ifdef PNG_USE_ABS - sum += 128 - abs(v - 128); + sum += 128 - abs((int)v - 128); #else sum += (v < 128) ? v : 256 - v; #endif diff --git a/3rdparty/zlib/gzread.c b/3rdparty/zlib/gzread.c index 956b91ea7d..e75cae64dc 100644 --- a/3rdparty/zlib/gzread.c +++ b/3rdparty/zlib/gzread.c @@ -316,7 +316,7 @@ local z_size_t gz_read(state, buf, len) /* set n to the maximum amount of len that fits in an unsigned int */ n = -1; if (n > len) - n = len; + n = (int)len; /* first just try copying data from the output buffer */ if (state->x.have) { @@ -397,7 +397,7 @@ int ZEXPORT gzread(file, buf, len) } /* read len or fewer bytes to buf */ - len = gz_read(state, buf, len); + len = (int)gz_read(state, buf, len); /* check for an error */ if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) @@ -469,7 +469,7 @@ int ZEXPORT gzgetc(file) } /* nothing there -- try gz_read() */ - ret = gz_read(state, buf, 1); + ret = (int)gz_read(state, buf, 1); return ret < 1 ? -1 : buf[0]; } diff --git a/3rdparty/zlib/gzwrite.c b/3rdparty/zlib/gzwrite.c index c7b5651d70..57a1cc70c8 100644 --- a/3rdparty/zlib/gzwrite.c +++ b/3rdparty/zlib/gzwrite.c @@ -209,7 +209,7 @@ local z_size_t gz_write(state, buf, len) state->in); copy = state->size - have; if (copy > len) - copy = len; + copy = (int)len; memcpy(state->in + have, buf, copy); state->strm.avail_in += copy; state->x.pos += copy; @@ -229,7 +229,7 @@ local z_size_t gz_write(state, buf, len) do { unsigned n = (unsigned)-1; if (n > len) - n = len; + n = (int)len; state->strm.avail_in = n; state->x.pos += n; if (gz_comp(state, Z_NO_FLUSH) == -1) @@ -368,7 +368,7 @@ int ZEXPORT gzputs(file, str) /* write string */ len = strlen(str); - ret = gz_write(state, str, len); + ret = (int)gz_write(state, str, len); return ret == 0 && len != 0 ? -1 : ret; } From ca46171246cac524af4ce81146cbc5f304fee15c Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 7 Dec 2017 19:16:11 +0300 Subject: [PATCH 3/8] 3rdparty: libpng patch --- 3rdparty/libpng/opencv-libpng.patch | 38 +++++++++++++++++++++++++++++ 3rdparty/libpng/pngpriv.h | 8 +++--- 2 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 3rdparty/libpng/opencv-libpng.patch diff --git a/3rdparty/libpng/opencv-libpng.patch b/3rdparty/libpng/opencv-libpng.patch new file mode 100644 index 0000000000..e760e8d89f --- /dev/null +++ b/3rdparty/libpng/opencv-libpng.patch @@ -0,0 +1,38 @@ +--- a/3rdparty/libpng/pngpriv.h ++++ b/3rdparty/libpng/pngpriv.h +@@ -214,7 +214,7 @@ + # endif + #endif + +-#if PNG_INTEL_SSE_OPT > 0 ++#if defined(PNG_INTEL_SSE_OPT) && PNG_INTEL_SSE_OPT > 0 + # ifndef PNG_INTEL_SSE_IMPLEMENTATION + # if defined(__SSE4_1__) || defined(__AVX__) + /* We are not actually using AVX, but checking for AVX is the best +@@ -547,7 +547,7 @@ + + /* Memory model/platform independent fns */ + #ifndef PNG_ABORT +-# ifdef _WINDOWS_ ++# if defined(_WINDOWS_) && !defined(WINRT) + # define PNG_ABORT() ExitProcess(0) + # else + # define PNG_ABORT() abort() +@@ -1340,7 +1340,7 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_vsx,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); + #endif + +-#if PNG_INTEL_SSE_IMPLEMENTATION > 0 ++#if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 + PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop + row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); + PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop +@@ -2099,7 +2099,7 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); + #endif + +-# if PNG_INTEL_SSE_IMPLEMENTATION > 0 ++# if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 + PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, + (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); + # endif \ No newline at end of file diff --git a/3rdparty/libpng/pngpriv.h b/3rdparty/libpng/pngpriv.h index 1f2e90f2b3..4e7278f174 100644 --- a/3rdparty/libpng/pngpriv.h +++ b/3rdparty/libpng/pngpriv.h @@ -214,7 +214,7 @@ # endif #endif -#if PNG_INTEL_SSE_OPT > 0 +#if defined(PNG_INTEL_SSE_OPT) && PNG_INTEL_SSE_OPT > 0 # ifndef PNG_INTEL_SSE_IMPLEMENTATION # if defined(__SSE4_1__) || defined(__AVX__) /* We are not actually using AVX, but checking for AVX is the best @@ -547,7 +547,7 @@ /* Memory model/platform independent fns */ #ifndef PNG_ABORT -# ifdef _WINDOWS_ +# if defined(_WINDOWS_) && !defined(WINRT) # define PNG_ABORT() ExitProcess(0) # else # define PNG_ABORT() abort() @@ -1340,7 +1340,7 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_vsx,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); #endif -#if PNG_INTEL_SSE_IMPLEMENTATION > 0 +#if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop @@ -2099,7 +2099,7 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); #endif -# if PNG_INTEL_SSE_IMPLEMENTATION > 0 +# if defined(PNG_INTEL_SSE_IMPLEMENTATION) && PNG_INTEL_SSE_IMPLEMENTATION > 0 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); # endif From 83b5b86f7de8e3b1584719a11182514d360fc21d Mon Sep 17 00:00:00 2001 From: Suleyman TURKMEN Date: Sun, 22 Oct 2017 13:06:42 +0300 Subject: [PATCH 4/8] 3rdparty: update libjpeg 9b --- 3rdparty/libjpeg/README | 107 ++- 3rdparty/libjpeg/change.log | 50 + 3rdparty/libjpeg/jcapimin.c | 14 +- 3rdparty/libjpeg/jcapistd.c | 7 +- 3rdparty/libjpeg/jcarith.c | 337 +++---- 3rdparty/libjpeg/jccoefct.c | 164 ++-- 3rdparty/libjpeg/jccolor.c | 209 +++-- 3rdparty/libjpeg/jcdctmgr.c | 271 +++--- 3rdparty/libjpeg/jchuff.c | 301 +++---- 3rdparty/libjpeg/jcinit.c | 21 +- 3rdparty/libjpeg/jcmainct.c | 102 +-- 3rdparty/libjpeg/jcmarker.c | 74 +- 3rdparty/libjpeg/jcmaster.c | 188 ++-- 3rdparty/libjpeg/jconfig.h | 114 +-- 3rdparty/libjpeg/jcparam.c | 154 ++-- 3rdparty/libjpeg/jcprepct.c | 122 +-- 3rdparty/libjpeg/jcsample.c | 116 +-- 3rdparty/libjpeg/jctrans.c | 98 +- 3rdparty/libjpeg/jdapimin.c | 77 +- 3rdparty/libjpeg/jdapistd.c | 53 +- 3rdparty/libjpeg/jdarith.c | 270 +++--- 3rdparty/libjpeg/jdatadst.c | 8 +- 3rdparty/libjpeg/jdatasrc.c | 12 +- 3rdparty/libjpeg/jdcoefct.c | 362 ++++---- 3rdparty/libjpeg/jdcolor.c | 295 ++++-- 3rdparty/libjpeg/jdct.h | 110 ++- 3rdparty/libjpeg/jddctmgr.c | 140 +-- 3rdparty/libjpeg/jdhuff.c | 742 +++++++-------- 3rdparty/libjpeg/jdinput.c | 115 +-- 3rdparty/libjpeg/jdmainct.c | 48 +- 3rdparty/libjpeg/jdmarker.c | 268 +++--- 3rdparty/libjpeg/jdmaster.c | 118 +-- 3rdparty/libjpeg/jdmerge.c | 165 ++-- 3rdparty/libjpeg/jdpostct.c | 102 +-- 3rdparty/libjpeg/jdsample.c | 81 +- 3rdparty/libjpeg/jdtrans.c | 16 +- 3rdparty/libjpeg/jerror.c | 24 +- 3rdparty/libjpeg/jerror.h | 68 +- 3rdparty/libjpeg/jfdctflt.c | 6 +- 3rdparty/libjpeg/jfdctfst.c | 6 +- 3rdparty/libjpeg/jfdctint.c | 1509 ++++++++++++++++--------------- 3rdparty/libjpeg/jidctflt.c | 45 +- 3rdparty/libjpeg/jidctfst.c | 137 ++- 3rdparty/libjpeg/jidctint.c | 1704 +++++++++++++++++++---------------- 3rdparty/libjpeg/jmemansi.c | 12 +- 3rdparty/libjpeg/jmemmgr.c | 174 ++-- 3rdparty/libjpeg/jmemnobs.c | 4 +- 3rdparty/libjpeg/jmemsys.h | 30 +- 3rdparty/libjpeg/jmorecfg.h | 80 +- 3rdparty/libjpeg/jpegint.h | 124 +-- 3rdparty/libjpeg/jpeglib.h | 203 +++-- 3rdparty/libjpeg/jquant1.c | 176 ++-- 3rdparty/libjpeg/jquant2.c | 270 +++--- 3rdparty/libjpeg/jutils.c | 6 +- 3rdparty/libjpeg/jversion.h | 6 +- 55 files changed, 5276 insertions(+), 4739 deletions(-) diff --git a/3rdparty/libjpeg/README b/3rdparty/libjpeg/README index fc5ca5d458..4c8e82e9ba 100644 --- a/3rdparty/libjpeg/README +++ b/3rdparty/libjpeg/README @@ -1,8 +1,8 @@ The Independent JPEG Group's JPEG software ========================================== -README for release 9 of 13-Jan-2013 -=================================== +README for release 9b of 17-Jan-2016 +==================================== This distribution contains the ninth public release of the Independent JPEG Group's free JPEG software. You are welcome to redistribute this software and @@ -14,7 +14,7 @@ Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers, and other members of the Independent JPEG Group. IJG is not affiliated with the ISO/IEC JTC1/SC29/WG1 standards committee -(also known as JPEG, together with ITU-T SG16). +(previously known as JPEG, together with ITU-T SG16). DOCUMENTATION ROADMAP @@ -60,7 +60,7 @@ OVERVIEW This package contains C software to implement JPEG image encoding, decoding, and transcoding. JPEG (pronounced "jay-peg") is a standardized compression -method for full-color and gray-scale images. +method for full-color and grayscale images. This software implements JPEG baseline, extended-sequential, and progressive compression processes. Provision is made for supporting all variants of these @@ -115,7 +115,7 @@ with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. -This software is copyright (C) 1991-2013, Thomas G. Lane, Guido Vollbeding. +This software is copyright (C) 1991-2016, Thomas G. Lane, Guido Vollbeding. All Rights Reserved except as specified below. Permission is hereby granted to use, copy, modify, and distribute this @@ -153,16 +153,11 @@ ltmain.sh). Another support script, install-sh, is copyright by X Consortium but is also freely distributable. The IJG distribution formerly included code to read and write GIF files. -To avoid entanglement with the Unisys LZW patent, GIF reading support has -been removed altogether, and the GIF writer has been simplified to produce -"uncompressed GIFs". This technique does not use the LZW algorithm; the -resulting GIF files are larger than usual, but are readable by all standard -GIF decoders. - -We are required to state that - "The Graphics Interchange Format(c) is the Copyright property of - CompuServe Incorporated. GIF(sm) is a Service Mark property of - CompuServe Incorporated." +To avoid entanglement with the Unisys LZW patent (now expired), GIF reading +support has been removed altogether, and the GIF writer has been simplified +to produce "uncompressed GIFs". This technique does not use the LZW +algorithm; the resulting GIF files are larger than usual, but are readable +by all standard GIF decoders. REFERENCES @@ -176,8 +171,8 @@ The best short technical introduction to the JPEG compression algorithm is Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. (Adjacent articles in that issue discuss MPEG motion picture compression, applications of JPEG, and related topics.) If you don't have the CACM issue -handy, a PostScript file containing a revised version of Wallace's article is -available at http://www.ijg.org/files/wallace.ps.gz. The file (actually +handy, a PDF file containing a revised version of Wallace's article is +available at http://www.ijg.org/files/Wallace.JPEG.pdf. The file (actually a preprint for an article that appeared in IEEE Trans. Consumer Electronics) omits the sample images that appeared in CACM, but it includes corrections and some added material. Note: the Wallace article is copyright ACM and IEEE, @@ -225,14 +220,13 @@ WG1 N 6080 with title "JPEG 9 Lossless Coding", June/July 2012, Paris, France. The JPEG standard does not specify all details of an interchangeable file -format. For the omitted details we follow the "JFIF" conventions, revision -1.02. JFIF 1.02 has been adopted as an Ecma International Technical Report -and thus received a formal publication status. It is available as a free -download in PDF format from -http://www.ecma-international.org/publications/techreports/E-TR-098.htm. -A PostScript version of the JFIF document is available at -http://www.ijg.org/files/jfif.ps.gz. There is also a plain text version at -http://www.ijg.org/files/jfif.txt.gz, but it is missing the figures. +format. For the omitted details we follow the "JFIF" conventions, version 2. +JFIF version 1 has been adopted as Recommendation ITU-T T.871 (05/2011) : +Information technology - Digital compression and coding of continuous-tone +still images: JPEG File Interchange Format (JFIF). It is available as a +free download in PDF file format from http://www.itu.int/rec/T-REC-T.871. +A PDF file of the older JFIF document is available at +http://www.w3.org/Graphics/JPEG/jfif3.pdf. The TIFF 6.0 file format specification can be obtained by FTP from ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme @@ -252,8 +246,8 @@ ARCHIVE LOCATIONS The "official" archive site for this software is www.ijg.org. The most recent released version can always be found there in directory "files". This particular version will be archived as -http://www.ijg.org/files/jpegsrc.v9.tar.gz, and in Windows-compatible -"zip" archive format as http://www.ijg.org/files/jpegsr9.zip. +http://www.ijg.org/files/jpegsrc.v9b.tar.gz, and in Windows-compatible +"zip" archive format as http://www.ijg.org/files/jpegsr9b.zip. The JPEG FAQ (Frequently Asked Questions) article is a source of some general information about JPEG. @@ -280,7 +274,7 @@ Thank to Thomas Wiegand and Gary Sullivan for inviting me to the Joint Video Team (MPEG & ITU) meeting in Geneva, Switzerland. Thank to Thomas Richter and Daniel Lee for inviting me to the -ISO/IEC JTC1/SC29/WG1 (also known as JPEG, together with ITU-T SG16) +ISO/IEC JTC1/SC29/WG1 (previously known as JPEG, together with ITU-T SG16) meeting in Berlin, Germany. Thank to John Korejwa and Massimo Ballerini for inviting me to @@ -306,10 +300,10 @@ design and development of this singular software package. FILE FORMAT WARS ================ -The ISO/IEC JTC1/SC29/WG1 standards committee (also known as JPEG, together -with ITU-T SG16) currently promotes different formats containing the name -"JPEG" which is misleading because these formats are incompatible with -original DCT-based JPEG and are based on faulty technologies. +The ISO/IEC JTC1/SC29/WG1 standards committee (previously known as JPEG, +together with ITU-T SG16) currently promotes different formats containing +the name "JPEG" which is misleading because these formats are incompatible +with original DCT-based JPEG and are based on faulty technologies. IJG therefore does not and will not support such momentary mistakes (see REFERENCES). There exist also distributions under the name "OpenJPEG" promoting such @@ -322,9 +316,13 @@ Don't use an incompatible file format! (In any case, our decoder will remain capable of reading existing JPEG image files indefinitely.) -Furthermore, the ISO committee pretends to be "responsible for the popular -JPEG" in their public reports which is not true because they don't respond to -actual requirements for the maintenance of the original JPEG specification. +The ISO committee pretends to be "responsible for the popular JPEG" in their +public reports which is not true because they don't respond to actual +requirements for the maintenance of the original JPEG specification. +Furthermore, the ISO committee pretends to "ensure interoperability" with +their standards which is not true because their "standards" support only +application-specific and proprietary use cases and contain mathematically +incorrect code. There are currently different distributions in circulation containing the name "libjpeg" which is misleading because they don't have the features and @@ -332,19 +330,46 @@ are incompatible with formats supported by actual IJG libjpeg distributions. One of those fakes is released by members of the ISO committee and just uses the name of libjpeg for misdirection of people, similar to the abuse of the name JPEG as described above, while having nothing in common with actual IJG -libjpeg distributions. -The other one claims to be a "derivative" or "fork" of the original libjpeg -and violates the license conditions as described under LEGAL ISSUES above. -We have no sympathy for the release of misleading and illegal distributions -derived from obsolete code bases. +libjpeg distributions and containing mathematically incorrect code. +The other one claims to be a "derivative" or "fork" of the original libjpeg, +but violates the license conditions as described under LEGAL ISSUES above +and violates basic C programming properties. +We have no sympathy for the release of misleading, incorrect and illegal +distributions derived from obsolete code bases. Don't use an obsolete code base! +According to the UCC (Uniform Commercial Code) law, IJG has the lawful and +legal right to foreclose on certain standardization bodies and other +institutions or corporations that knowingly perform substantial and +systematic deceptive acts and practices, fraud, theft, and damaging of the +value of the people of this planet without their knowing, willing and +intentional consent. +The titles, ownership, and rights of these institutions and all their assets +are now duly secured and held in trust for the free people of this planet. +People of the planet, on every country, may have a financial interest in +the assets of these former principals, agents, and beneficiaries of the +foreclosed institutions and corporations. +IJG asserts what is: that each man, woman, and child has unalienable value +and rights granted and deposited in them by the Creator and not any one of +the people is subordinate to any artificial principality, corporate fiction +or the special interest of another without their appropriate knowing, +willing and intentional consent made by contract or accommodation agreement. +IJG expresses that which already was. +The people have already determined and demanded that public administration +entities, national governments, and their supporting judicial systems must +be fully transparent, accountable, and liable. +IJG has secured the value for all concerned free people of the planet. + +A partial list of foreclosed institutions and corporations ("Hall of Shame") +is currently prepared and will be published later. + TO DO ===== Version 9 is the second release of a new generation JPEG standard -to overcome the limitations of the original JPEG specification. +to overcome the limitations of the original JPEG specification, +and is the first true source reference JPEG codec. More features are being prepared for coming releases... Please send bug reports, offers of help, etc. to jpeg-info@jpegclub.org. diff --git a/3rdparty/libjpeg/change.log b/3rdparty/libjpeg/change.log index a1d94ff47e..b8439f4143 100644 --- a/3rdparty/libjpeg/change.log +++ b/3rdparty/libjpeg/change.log @@ -1,6 +1,56 @@ CHANGE LOG for Independent JPEG Group's JPEG software +Version 9b 17-Jan-2016 +----------------------- + +Improvements and optimizations in DCT and color calculations. +Normalize range limit array composition and access pattern. +Thank to Sia Furler and Maddie Ziegler for inspiration. + +Use merged upsample with scaled DCT sizes larger than 8. +Thank to Taylor Hatala for inspiration. + +Check for excessive comment lengths in argument parsing in wrjpgcom.c. +Thank to Julian Cohen for hint. + +Add makefile.b32 for use with Borland C++ 32-bit (bcc32). +Thank to Joe Slater for contribution. + +Document 'f' specifier for jpegtran -crop specification. +Thank to Michele Martone for suggestion. + +Use defined value from header instead of hardwired number in rdswitch.c. +Thank to Robert Sprowson for hint. + + +Version 9a 19-Jan-2014 +----------------------- + +Add support for wide gamut color spaces (JFIF version 2). +Improve clarity and accuracy in color conversion modules. +Note: Requires rebuild of test images. + +Extend the bit depth support to all values from 8 to 12 +(BITS_IN_JSAMPLE configuration option in jmorecfg.h). +jpegtran now supports N bits sample data precision with all N from 8 to 12 +in a single instance. Thank to Roland Fassauer for inspiration. + +Try to resolve issues with new boolean type definition. +Thank also to v4hn for suggestion. + +Enable option to use default Huffman tables for lossless compression +(for hardware solution), and in this case improve lossless RGB compression +with reversible color transform. Thank to Benny Alexandar for hint. + +Extend the entropy decoding structure, so that extraneous bytes between +compressed scan data and following marker can be reported correctly. +Thank to Nigel Tao for hint. + +Add jpegtran -wipe option and extension for -crop. +Thank to Andrew Senior, David Clunie, and Josef Schmid for suggestion. + + Version 9 13-Jan-2013 ---------------------- diff --git a/3rdparty/libjpeg/jcapimin.c b/3rdparty/libjpeg/jcapimin.c index c4e637b370..639ce86f44 100644 --- a/3rdparty/libjpeg/jcapimin.c +++ b/3rdparty/libjpeg/jcapimin.c @@ -37,8 +37,8 @@ jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) if (version != JPEG_LIB_VERSION) ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); if (structsize != SIZEOF(struct jpeg_compress_struct)) - ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, - (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); /* For debugging purposes, we zero the whole master structure. * But the application has already set the err pointer, and may have set @@ -169,15 +169,15 @@ jpeg_finish_compress (j_compress_ptr cinfo) (*cinfo->master->prepare_for_pass) (cinfo); for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) iMCU_row; - cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + cinfo->progress->pass_counter = (long) iMCU_row; + cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* We bypass the main controller and invoke coef controller directly; * all work is being done from the coefficient buffer. */ if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) - ERREXIT(cinfo, JERR_CANT_SUSPEND); + ERREXIT(cinfo, JERR_CANT_SUSPEND); } (*cinfo->master->finish_pass) (cinfo); } @@ -198,7 +198,7 @@ jpeg_finish_compress (j_compress_ptr cinfo) GLOBAL(void) jpeg_write_marker (j_compress_ptr cinfo, int marker, - const JOCTET *dataptr, unsigned int datalen) + const JOCTET *dataptr, unsigned int datalen) { JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); diff --git a/3rdparty/libjpeg/jcapistd.c b/3rdparty/libjpeg/jcapistd.c index 34a2ea419f..0917afa97d 100644 --- a/3rdparty/libjpeg/jcapistd.c +++ b/3rdparty/libjpeg/jcapistd.c @@ -2,6 +2,7 @@ * jcapistd.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -75,7 +76,7 @@ jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) GLOBAL(JDIMENSION) jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION num_lines) + JDIMENSION num_lines) { JDIMENSION row_ctr, rows_left; @@ -118,7 +119,7 @@ jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, GLOBAL(JDIMENSION) jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION num_lines) + JDIMENSION num_lines) { JDIMENSION lines_per_iMCU_row; @@ -145,7 +146,7 @@ jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, (*cinfo->master->pass_startup) (cinfo); /* Verify that at least one iMCU row has been passed. */ - lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; + lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size; if (num_lines < lines_per_iMCU_row) ERREXIT(cinfo, JERR_BUFFER_SIZE); diff --git a/3rdparty/libjpeg/jcarith.c b/3rdparty/libjpeg/jcarith.c index d68b67000f..a64190e72e 100644 --- a/3rdparty/libjpeg/jcarith.c +++ b/3rdparty/libjpeg/jcarith.c @@ -1,7 +1,7 @@ /* * jcarith.c * - * Developed 1997-2012 by Guido Vollbeding. + * Developed 1997-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -103,9 +103,9 @@ typedef arith_entropy_encoder * arith_entropy_ptr; #ifdef RIGHT_SHIFT_IS_UNSIGNED #define ISHIFT_TEMPS int ishift_temp; #define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ - (ishift_temp >> (shft))) + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) #else #define ISHIFT_TEMPS #define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) @@ -149,11 +149,11 @@ finish_pass (j_compress_ptr cinfo) /* One final overflow has to be handled */ if (e->buffer >= 0) { if (e->zc) - do emit_byte(0x00, cinfo); - while (--e->zc); + do emit_byte(0x00, cinfo); + while (--e->zc); emit_byte(e->buffer + 1, cinfo); if (e->buffer + 1 == 0xFF) - emit_byte(0x00, cinfo); + emit_byte(0x00, cinfo); } e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ e->sc = 0; @@ -162,17 +162,17 @@ finish_pass (j_compress_ptr cinfo) ++e->zc; else if (e->buffer >= 0) { if (e->zc) - do emit_byte(0x00, cinfo); - while (--e->zc); + do emit_byte(0x00, cinfo); + while (--e->zc); emit_byte(e->buffer, cinfo); } if (e->sc) { if (e->zc) - do emit_byte(0x00, cinfo); - while (--e->zc); + do emit_byte(0x00, cinfo); + while (--e->zc); do { - emit_byte(0xFF, cinfo); - emit_byte(0x00, cinfo); + emit_byte(0xFF, cinfo); + emit_byte(0x00, cinfo); } while (--e->sc); } } @@ -187,7 +187,7 @@ finish_pass (j_compress_ptr cinfo) if (e->c & 0x7F800L) { emit_byte((e->c >> 11) & 0xFF, cinfo); if (((e->c >> 11) & 0xFF) == 0xFF) - emit_byte(0x00, cinfo); + emit_byte(0x00, cinfo); } } } @@ -216,7 +216,7 @@ finish_pass (j_compress_ptr cinfo) */ LOCAL(void) -arith_encode (j_compress_ptr cinfo, unsigned char *st, int val) +arith_encode (j_compress_ptr cinfo, unsigned char *st, int val) { register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy; register unsigned char nl, nm; @@ -266,43 +266,43 @@ arith_encode (j_compress_ptr cinfo, unsigned char *st, int val) /* Another byte is ready for output */ temp = e->c >> 19; if (temp > 0xFF) { - /* Handle overflow over all stacked 0xFF bytes */ - if (e->buffer >= 0) { - if (e->zc) - do emit_byte(0x00, cinfo); - while (--e->zc); - emit_byte(e->buffer + 1, cinfo); - if (e->buffer + 1 == 0xFF) - emit_byte(0x00, cinfo); - } - e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ - e->sc = 0; - /* Note: The 3 spacer bits in the C register guarantee - * that the new buffer byte can't be 0xFF here - * (see page 160 in the P&M JPEG book). */ - e->buffer = temp & 0xFF; /* new output byte, might overflow later */ + /* Handle overflow over all stacked 0xFF bytes */ + if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer + 1, cinfo); + if (e->buffer + 1 == 0xFF) + emit_byte(0x00, cinfo); + } + e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */ + e->sc = 0; + /* Note: The 3 spacer bits in the C register guarantee + * that the new buffer byte can't be 0xFF here + * (see page 160 in the P&M JPEG book). */ + e->buffer = temp & 0xFF; /* new output byte, might overflow later */ } else if (temp == 0xFF) { - ++e->sc; /* stack 0xFF byte (which might overflow later) */ + ++e->sc; /* stack 0xFF byte (which might overflow later) */ } else { - /* Output all stacked 0xFF bytes, they will not overflow any more */ - if (e->buffer == 0) - ++e->zc; - else if (e->buffer >= 0) { - if (e->zc) - do emit_byte(0x00, cinfo); - while (--e->zc); - emit_byte(e->buffer, cinfo); - } - if (e->sc) { - if (e->zc) - do emit_byte(0x00, cinfo); - while (--e->zc); - do { - emit_byte(0xFF, cinfo); - emit_byte(0x00, cinfo); - } while (--e->sc); - } - e->buffer = temp & 0xFF; /* new output byte (can still overflow) */ + /* Output all stacked 0xFF bytes, they will not overflow any more */ + if (e->buffer == 0) + ++e->zc; + else if (e->buffer >= 0) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + emit_byte(e->buffer, cinfo); + } + if (e->sc) { + if (e->zc) + do emit_byte(0x00, cinfo); + while (--e->zc); + do { + emit_byte(0xFF, cinfo); + emit_byte(0x00, cinfo); + } while (--e->sc); + } + e->buffer = temp & 0xFF; /* new output byte (can still overflow) */ } e->c &= 0x7FFFFL; e->ct += 8; @@ -362,7 +362,6 @@ METHODDEF(boolean) encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; - JBLOCKROW block; unsigned char *st; int blkn, ci, tbl; int v, v2, m; @@ -381,14 +380,13 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; ci = cinfo->MCU_membership[blkn]; tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; /* Compute the DC value after the required point transform by Al. * This is simply an arithmetic right shift. */ - m = IRIGHT_SHIFT((int) ((*block)[0]), cinfo->Al); + m = IRIGHT_SHIFT((int) (MCU_data[blkn][0][0]), cinfo->Al); /* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */ @@ -405,38 +403,38 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* Figure F.6: Encoding nonzero value v */ /* Figure F.7: Encoding the sign of v */ if (v > 0) { - arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ - st += 2; /* Table F.4: SP = S0 + 2 */ - entropy->dc_context[ci] = 4; /* small positive diff category */ + arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ + st += 2; /* Table F.4: SP = S0 + 2 */ + entropy->dc_context[ci] = 4; /* small positive diff category */ } else { - v = -v; - arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ - st += 3; /* Table F.4: SN = S0 + 3 */ - entropy->dc_context[ci] = 8; /* small negative diff category */ + v = -v; + arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ + st += 3; /* Table F.4: SN = S0 + 3 */ + entropy->dc_context[ci] = 8; /* small negative diff category */ } /* Figure F.8: Encoding the magnitude category of v */ m = 0; if (v -= 1) { - arith_encode(cinfo, st, 1); - m = 1; - v2 = v; - st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ - while (v2 >>= 1) { - arith_encode(cinfo, st, 1); - m <<= 1; - st += 1; - } + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } } arith_encode(cinfo, st, 0); /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) - entropy->dc_context[ci] = 0; /* zero diff category */ + entropy->dc_context[ci] = 0; /* zero diff category */ else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) - entropy->dc_context[ci] += 8; /* large diff category */ + entropy->dc_context[ci] += 8; /* large diff category */ /* Figure F.9: Encoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) - arith_encode(cinfo, st, (m & v) ? 1 : 0); + arith_encode(cinfo, st, (m & v) ? 1 : 0); } } @@ -453,11 +451,11 @@ METHODDEF(boolean) encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + const int * natural_order; JBLOCKROW block; unsigned char *st; int tbl, k, ke; int v, v2, m; - const int * natural_order; /* Emit restart marker if needed */ if (cinfo->restart_interval) { @@ -499,18 +497,18 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) arith_encode(cinfo, st, 0); /* EOB decision */ for (;;) { if ((v = (*block)[natural_order[++k]]) >= 0) { - if (v >>= cinfo->Al) { - arith_encode(cinfo, st + 1, 1); - arith_encode(cinfo, entropy->fixed_bin, 0); - break; - } + if (v >>= cinfo->Al) { + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 0); + break; + } } else { - v = -v; - if (v >>= cinfo->Al) { - arith_encode(cinfo, st + 1, 1); - arith_encode(cinfo, entropy->fixed_bin, 1); - break; - } + v = -v; + if (v >>= cinfo->Al) { + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 1); + break; + } } arith_encode(cinfo, st + 1, 0); st += 3; @@ -523,15 +521,15 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) m = 1; v2 = v; if (v2 >>= 1) { - arith_encode(cinfo, st, 1); - m <<= 1; - st = entropy->ac_stats[tbl] + - (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); - while (v2 >>= 1) { - arith_encode(cinfo, st, 1); - m <<= 1; - st += 1; - } + arith_encode(cinfo, st, 1); + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } } } arith_encode(cinfo, st, 0); @@ -552,6 +550,8 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* * MCU encoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, + * although the spec is not very clear on the point. */ METHODDEF(boolean) @@ -593,11 +593,11 @@ METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; + const int * natural_order; JBLOCKROW block; unsigned char *st; int tbl, k, ke, kex; int v; - const int * natural_order; /* Emit restart marker if needed */ if (cinfo->restart_interval) { @@ -649,26 +649,26 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) arith_encode(cinfo, st, 0); /* EOB decision */ for (;;) { if ((v = (*block)[natural_order[++k]]) >= 0) { - if (v >>= cinfo->Al) { - if (v >> 1) /* previously nonzero coef */ - arith_encode(cinfo, st + 2, (v & 1)); - else { /* newly nonzero coef */ - arith_encode(cinfo, st + 1, 1); - arith_encode(cinfo, entropy->fixed_bin, 0); - } - break; - } + if (v >>= cinfo->Al) { + if (v >> 1) /* previously nonzero coef */ + arith_encode(cinfo, st + 2, (v & 1)); + else { /* newly nonzero coef */ + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 0); + } + break; + } } else { - v = -v; - if (v >>= cinfo->Al) { - if (v >> 1) /* previously nonzero coef */ - arith_encode(cinfo, st + 2, (v & 1)); - else { /* newly nonzero coef */ - arith_encode(cinfo, st + 1, 1); - arith_encode(cinfo, entropy->fixed_bin, 1); - } - break; - } + v = -v; + if (v >>= cinfo->Al) { + if (v >> 1) /* previously nonzero coef */ + arith_encode(cinfo, st + 2, (v & 1)); + else { /* newly nonzero coef */ + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 1); + } + break; + } } arith_encode(cinfo, st + 1, 0); st += 3; @@ -692,12 +692,13 @@ METHODDEF(boolean) encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy; - jpeg_component_info * compptr; + const int * natural_order; JBLOCKROW block; unsigned char *st; - int blkn, ci, tbl, k, ke; + int tbl, k, ke; int v, v2, m; - const int * natural_order; + int blkn, ci; + jpeg_component_info * compptr; /* Emit restart marker if needed */ if (cinfo->restart_interval) { @@ -735,38 +736,38 @@ encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* Figure F.6: Encoding nonzero value v */ /* Figure F.7: Encoding the sign of v */ if (v > 0) { - arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ - st += 2; /* Table F.4: SP = S0 + 2 */ - entropy->dc_context[ci] = 4; /* small positive diff category */ + arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */ + st += 2; /* Table F.4: SP = S0 + 2 */ + entropy->dc_context[ci] = 4; /* small positive diff category */ } else { - v = -v; - arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ - st += 3; /* Table F.4: SN = S0 + 3 */ - entropy->dc_context[ci] = 8; /* small negative diff category */ + v = -v; + arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */ + st += 3; /* Table F.4: SN = S0 + 3 */ + entropy->dc_context[ci] = 8; /* small negative diff category */ } /* Figure F.8: Encoding the magnitude category of v */ m = 0; if (v -= 1) { - arith_encode(cinfo, st, 1); - m = 1; - v2 = v; - st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ - while (v2 >>= 1) { - arith_encode(cinfo, st, 1); - m <<= 1; - st += 1; - } + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } } arith_encode(cinfo, st, 0); /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) - entropy->dc_context[ci] = 0; /* zero diff category */ + entropy->dc_context[ci] = 0; /* zero diff category */ else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) - entropy->dc_context[ci] += 8; /* large diff category */ + entropy->dc_context[ci] += 8; /* large diff category */ /* Figure F.9: Encoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) - arith_encode(cinfo, st, (m & v) ? 1 : 0); + arith_encode(cinfo, st, (m & v) ? 1 : 0); } /* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */ @@ -784,42 +785,42 @@ encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data) st = entropy->ac_stats[tbl] + 3 * k; arith_encode(cinfo, st, 0); /* EOB decision */ while ((v = (*block)[natural_order[++k]]) == 0) { - arith_encode(cinfo, st + 1, 0); - st += 3; + arith_encode(cinfo, st + 1, 0); + st += 3; } arith_encode(cinfo, st + 1, 1); /* Figure F.6: Encoding nonzero value v */ /* Figure F.7: Encoding the sign of v */ if (v > 0) { - arith_encode(cinfo, entropy->fixed_bin, 0); + arith_encode(cinfo, entropy->fixed_bin, 0); } else { - v = -v; - arith_encode(cinfo, entropy->fixed_bin, 1); + v = -v; + arith_encode(cinfo, entropy->fixed_bin, 1); } st += 2; /* Figure F.8: Encoding the magnitude category of v */ m = 0; if (v -= 1) { - arith_encode(cinfo, st, 1); - m = 1; - v2 = v; - if (v2 >>= 1) { - arith_encode(cinfo, st, 1); - m <<= 1; - st = entropy->ac_stats[tbl] + - (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); - while (v2 >>= 1) { - arith_encode(cinfo, st, 1); - m <<= 1; - st += 1; - } - } + arith_encode(cinfo, st, 1); + m = 1; + v2 = v; + if (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (v2 >>= 1) { + arith_encode(cinfo, st, 1); + m <<= 1; + st += 1; + } + } } arith_encode(cinfo, st, 0); /* Figure F.9: Encoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) - arith_encode(cinfo, st, (m & v) ? 1 : 0); + arith_encode(cinfo, st, (m & v) ? 1 : 0); } /* Encode EOB decision only if k < cinfo->lim_Se */ if (k < cinfo->lim_Se) { @@ -856,14 +857,14 @@ start_pass (j_compress_ptr cinfo, boolean gather_statistics) if (cinfo->progressive_mode) { if (cinfo->Ah == 0) { if (cinfo->Ss == 0) - entropy->pub.encode_mcu = encode_mcu_DC_first; + entropy->pub.encode_mcu = encode_mcu_DC_first; else - entropy->pub.encode_mcu = encode_mcu_AC_first; + entropy->pub.encode_mcu = encode_mcu_AC_first; } else { if (cinfo->Ss == 0) - entropy->pub.encode_mcu = encode_mcu_DC_refine; + entropy->pub.encode_mcu = encode_mcu_DC_refine; else - entropy->pub.encode_mcu = encode_mcu_AC_refine; + entropy->pub.encode_mcu = encode_mcu_AC_refine; } } else entropy->pub.encode_mcu = encode_mcu; @@ -875,10 +876,10 @@ start_pass (j_compress_ptr cinfo, boolean gather_statistics) if (cinfo->Ss == 0 && cinfo->Ah == 0) { tbl = compptr->dc_tbl_no; if (tbl < 0 || tbl >= NUM_ARITH_TBLS) - ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); if (entropy->dc_stats[tbl] == NULL) - entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); + entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); /* Initialize DC predictions to 0 */ entropy->last_dc_val[ci] = 0; @@ -888,15 +889,15 @@ start_pass (j_compress_ptr cinfo, boolean gather_statistics) if (cinfo->Se) { tbl = compptr->ac_tbl_no; if (tbl < 0 || tbl >= NUM_ARITH_TBLS) - ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); if (entropy->ac_stats[tbl] == NULL) - entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); + entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); #ifdef CALCULATE_SPECTRAL_CONDITIONING if (cinfo->progressive_mode) - /* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */ - cinfo->arith_ac_K[tbl] = cinfo->Ss + ((8 + cinfo->Se - cinfo->Ss) >> 4); + /* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */ + cinfo->arith_ac_K[tbl] = cinfo->Ss + ((8 + cinfo->Se - cinfo->Ss) >> 4); #endif } } @@ -927,7 +928,7 @@ jinit_arith_encoder (j_compress_ptr cinfo) entropy = (arith_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(arith_entropy_encoder)); + SIZEOF(arith_entropy_encoder)); cinfo->entropy = &entropy->pub; entropy->pub.start_pass = start_pass; entropy->pub.finish_pass = finish_pass; diff --git a/3rdparty/libjpeg/jccoefct.c b/3rdparty/libjpeg/jccoefct.c index 2f0a4894e4..924a703dda 100644 --- a/3rdparty/libjpeg/jccoefct.c +++ b/3rdparty/libjpeg/jccoefct.c @@ -156,7 +156,7 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; - MCU_col_num++) { + MCU_col_num++) { /* Determine where data comes from in input_buf and do the DCT thing. * Each call on forward_DCT processes a horizontal row of DCT blocks * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks @@ -168,48 +168,48 @@ compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) */ blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - forward_DCT = cinfo->fdct->forward_DCT[compptr->component_index]; - blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; - xpos = MCU_col_num * compptr->MCU_sample_width; - ypos = yoffset * compptr->DCT_v_scaled_size; - /* ypos == (yoffset+yindex) * DCTSIZE */ - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - if (coef->iMCU_row_num < last_iMCU_row || - yoffset+yindex < compptr->last_row_height) { - (*forward_DCT) (cinfo, compptr, - input_buf[compptr->component_index], - coef->MCU_buffer[blkn], - ypos, xpos, (JDIMENSION) blockcnt); - if (blockcnt < compptr->MCU_width) { - /* Create some dummy blocks at the right edge of the image. */ - FMEMZERO((void FAR *) coef->MCU_buffer[blkn + blockcnt], - (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); - for (bi = blockcnt; bi < compptr->MCU_width; bi++) { - coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; - } - } - } else { - /* Create a row of dummy blocks at the bottom of the image. */ - FMEMZERO((void FAR *) coef->MCU_buffer[blkn], - compptr->MCU_width * SIZEOF(JBLOCK)); - for (bi = 0; bi < compptr->MCU_width; bi++) { - coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; - } - } - blkn += compptr->MCU_width; - ypos += compptr->DCT_v_scaled_size; - } + compptr = cinfo->cur_comp_info[ci]; + forward_DCT = cinfo->fdct->forward_DCT[compptr->component_index]; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + xpos = MCU_col_num * compptr->MCU_sample_width; + ypos = yoffset * compptr->DCT_v_scaled_size; + /* ypos == (yoffset+yindex) * DCTSIZE */ + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + (*forward_DCT) (cinfo, compptr, + input_buf[compptr->component_index], + coef->MCU_buffer[blkn], + ypos, xpos, (JDIMENSION) blockcnt); + if (blockcnt < compptr->MCU_width) { + /* Create some dummy blocks at the right edge of the image. */ + FMEMZERO((void FAR *) coef->MCU_buffer[blkn + blockcnt], + (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); + for (bi = blockcnt; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; + } + } + } else { + /* Create a row of dummy blocks at the bottom of the image. */ + FMEMZERO((void FAR *) coef->MCU_buffer[blkn], + compptr->MCU_width * SIZEOF(JBLOCK)); + for (bi = 0; bi < compptr->MCU_width; bi++) { + coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; + } + } + blkn += compptr->MCU_width; + ypos += compptr->DCT_v_scaled_size; + } } /* Try to write the MCU. In event of a suspension failure, we will * re-DCT the MCU on restart (a bit inefficient, could be fixed...) */ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->mcu_ctr = MCU_col_num; - return FALSE; + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; } } /* Completed an MCU row, but perhaps not an iMCU row */ @@ -286,16 +286,16 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) for (block_row = 0; block_row < block_rows; block_row++) { thisblockrow = buffer[block_row]; (*forward_DCT) (cinfo, compptr, input_buf[ci], thisblockrow, - (JDIMENSION) (block_row * compptr->DCT_v_scaled_size), - (JDIMENSION) 0, blocks_across); + (JDIMENSION) (block_row * compptr->DCT_v_scaled_size), + (JDIMENSION) 0, blocks_across); if (ndummy > 0) { - /* Create dummy blocks at the right edge of the image. */ - thisblockrow += blocks_across; /* => first dummy block */ - FMEMZERO((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); - lastDC = thisblockrow[-1][0]; - for (bi = 0; bi < ndummy; bi++) { - thisblockrow[bi][0] = lastDC; - } + /* Create dummy blocks at the right edge of the image. */ + thisblockrow += blocks_across; /* => first dummy block */ + FMEMZERO((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); + lastDC = thisblockrow[-1][0]; + for (bi = 0; bi < ndummy; bi++) { + thisblockrow[bi][0] = lastDC; + } } } /* If at end of image, create dummy block rows as needed. @@ -307,19 +307,19 @@ compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) blocks_across += ndummy; /* include lower right corner */ MCUs_across = blocks_across / h_samp_factor; for (block_row = block_rows; block_row < compptr->v_samp_factor; - block_row++) { - thisblockrow = buffer[block_row]; - lastblockrow = buffer[block_row-1]; - FMEMZERO((void FAR *) thisblockrow, - (size_t) (blocks_across * SIZEOF(JBLOCK))); - for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { - lastDC = lastblockrow[h_samp_factor-1][0]; - for (bi = 0; bi < h_samp_factor; bi++) { - thisblockrow[bi][0] = lastDC; - } - thisblockrow += h_samp_factor; /* advance to next MCU in row */ - lastblockrow += h_samp_factor; - } + block_row++) { + thisblockrow = buffer[block_row]; + lastblockrow = buffer[block_row-1]; + FMEMZERO((void FAR *) thisblockrow, + (size_t) (blocks_across * SIZEOF(JBLOCK))); + for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { + lastDC = lastblockrow[h_samp_factor-1][0]; + for (bi = 0; bi < h_samp_factor; bi++) { + thisblockrow[bi][0] = lastDC; + } + thisblockrow += h_samp_factor; /* advance to next MCU in row */ + lastblockrow += h_samp_factor; + } } } } @@ -369,25 +369,25 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; - MCU_col_num++) { + MCU_col_num++) { /* Construct list of pointers to DCT blocks belonging to this MCU */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - start_col = MCU_col_num * compptr->MCU_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < compptr->MCU_width; xindex++) { - coef->MCU_buffer[blkn++] = buffer_ptr++; - } - } + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } } /* Try to write the MCU. */ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->mcu_ctr = MCU_col_num; - return FALSE; + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; } } /* Completed an MCU row, but perhaps not an iMCU row */ @@ -413,7 +413,7 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_coef_controller)); + SIZEOF(my_coef_controller)); cinfo->coef = (struct jpeg_c_coef_controller *) coef; coef->pub.start_pass = start_pass_coef; @@ -426,14 +426,14 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) jpeg_component_info *compptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { + ci++, compptr++) { coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - (JDIMENSION) jround_up((long) compptr->width_in_blocks, - (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_blocks, - (long) compptr->v_samp_factor), - (JDIMENSION) compptr->v_samp_factor); + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) compptr->v_samp_factor); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); @@ -445,7 +445,7 @@ jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } diff --git a/3rdparty/libjpeg/jccolor.c b/3rdparty/libjpeg/jccolor.c index bfb2580a18..f6b4a493fd 100644 --- a/3rdparty/libjpeg/jccolor.c +++ b/3rdparty/libjpeg/jccolor.c @@ -2,7 +2,7 @@ * jccolor.c * * Copyright (C) 1991-1996, Thomas G. Lane. - * Modified 2011-2012 by Guido Vollbeding. + * Modified 2011-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -29,13 +29,25 @@ typedef my_color_converter * my_cconvert_ptr; /**************** RGB -> YCbCr conversion: most common case **************/ /* - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore - * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B - * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE - * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE - * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * YCbCr is defined per Recommendation ITU-R BT.601-7 (03/2011), + * previously known as Recommendation CCIR 601-1, except that Cb and Cr + * are normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * sRGB (standard RGB color space) is defined per IEC 61966-2-1:1999. + * sYCC (standard luma-chroma-chroma color space with extended gamut) + * is defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex F. + * bg-sRGB and bg-sYCC (big gamut standard color spaces) + * are defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex G. + * Note that the derived conversion coefficients given in some of these + * documents are imprecise. The general conversion equations are + * Y = Kr * R + (1 - Kr - Kb) * G + Kb * B + * Cb = 0.5 * (B - Y) / (1 - Kb) + * Cr = 0.5 * (R - Y) / (1 - Kr) + * With Kr = 0.299 and Kb = 0.114 (derived according to SMPTE RP 177-1993 + * from the 1953 FCC NTSC primaries and CIE Illuminant C), + * the conversion equations to be implemented are therefore + * Y = 0.299 * R + 0.587 * G + 0.114 * B + * Cb = -0.168735892 * R - 0.331264108 * G + 0.5 * B + CENTERJSAMPLE + * Cr = 0.5 * R - 0.418687589 * G - 0.081312411 * B + CENTERJSAMPLE * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) @@ -49,9 +61,9 @@ typedef my_color_converter * my_cconvert_ptr; * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times R,G,B for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 12-bit samples it is still acceptable. It's not very reasonable for - * 16-bit samples, but if you want lossless storage you shouldn't be changing - * colorspace anyway. + * for 9-bit to 12-bit samples it is still acceptable. It's not very + * reasonable for 16-bit samples, but if you want lossless storage you + * shouldn't be changing colorspace anyway. * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included * in the tables to save adding them separately in the inner loop. */ @@ -93,24 +105,24 @@ rgb_ycc_start (j_compress_ptr cinfo) /* Allocate and fill in the conversion tables. */ cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (TABLE_SIZE * SIZEOF(INT32))); + (TABLE_SIZE * SIZEOF(INT32))); for (i = 0; i <= MAXJSAMPLE; i++) { - rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; - rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; - rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; - rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; - rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; + rgb_ycc_tab[i+R_Y_OFF] = FIX(0.299) * i; + rgb_ycc_tab[i+G_Y_OFF] = FIX(0.587) * i; + rgb_ycc_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF; + rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.168735892)) * i; + rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.331264108)) * i; /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. * This ensures that the maximum output will round to MAXJSAMPLE * not MAXJSAMPLE+1, and thus that we don't have to range-limit. */ - rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; + rgb_ycc_tab[i+B_CB_OFF] = FIX(0.5) * i + CBCR_OFFSET + ONE_HALF-1; /* B=>Cb and R=>Cr tables are the same - rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; + rgb_ycc_tab[i+R_CR_OFF] = FIX(0.5) * i + CBCR_OFFSET + ONE_HALF-1; */ - rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; - rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; + rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.418687589)) * i; + rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.081312411)) * i; } } @@ -129,8 +141,8 @@ rgb_ycc_start (j_compress_ptr cinfo) METHODDEF(void) rgb_ycc_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register INT32 * ctab = cconvert->rgb_ycc_tab; @@ -157,16 +169,16 @@ rgb_ycc_convert (j_compress_ptr cinfo, */ /* Y */ outptr0[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); /* Cb */ outptr1[col] = (JSAMPLE) - ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) - >> SCALEBITS); + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); /* Cr */ outptr2[col] = (JSAMPLE) - ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) - >> SCALEBITS); + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); inptr += RGB_PIXELSIZE; } } @@ -185,8 +197,8 @@ rgb_ycc_convert (j_compress_ptr cinfo, METHODDEF(void) rgb_gray_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register INT32 * ctab = cconvert->rgb_ycc_tab; @@ -205,8 +217,8 @@ rgb_gray_convert (j_compress_ptr cinfo, b = GETJSAMPLE(inptr[RGB_BLUE]); /* Y */ outptr[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); inptr += RGB_PIXELSIZE; } } @@ -223,8 +235,8 @@ rgb_gray_convert (j_compress_ptr cinfo, METHODDEF(void) cmyk_ycck_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register INT32 * ctab = cconvert->rgb_ycc_tab; @@ -254,16 +266,16 @@ cmyk_ycck_convert (j_compress_ptr cinfo, */ /* Y */ outptr0[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); /* Cb */ outptr1[col] = (JSAMPLE) - ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) - >> SCALEBITS); + ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) + >> SCALEBITS); /* Cr */ outptr2[col] = (JSAMPLE) - ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) - >> SCALEBITS); + ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) + >> SCALEBITS); inptr += 4; } } @@ -274,12 +286,15 @@ cmyk_ycck_convert (j_compress_ptr cinfo, * Convert some rows of samples to the JPEG colorspace. * [R,G,B] to [R-G,G,B-G] conversion with modulo calculation * (forward reversible color transform). + * This can be seen as an adaption of the general RGB->YCbCr + * conversion equation with Kr = Kb = 0, while replacing the + * normalization by modulo calculation. */ METHODDEF(void) rgb_rgb1_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) { register int r, g, b; register JSAMPROW inptr; @@ -312,13 +327,13 @@ rgb_rgb1_convert (j_compress_ptr cinfo, /* * Convert some rows of samples to the JPEG colorspace. * This version handles grayscale output with no conversion. - * The source can be either plain grayscale or YCbCr (since Y == gray). + * The source can be either plain grayscale or YCC (since Y == gray). */ METHODDEF(void) grayscale_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) { int instride = cinfo->input_components; register JSAMPROW inptr; @@ -345,8 +360,8 @@ grayscale_convert (j_compress_ptr cinfo, METHODDEF(void) rgb_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) { register JSAMPROW inptr; register JSAMPROW outptr0, outptr1, outptr2; @@ -378,8 +393,8 @@ rgb_convert (j_compress_ptr cinfo, METHODDEF(void) null_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) { int ci; register int nc = cinfo->num_components; @@ -394,8 +409,8 @@ null_convert (j_compress_ptr cinfo, inptr = input_buf[0] + ci; outptr = output_buf[ci][output_row]; for (col = 0; col < num_cols; col++) { - *outptr++ = *inptr; /* don't need GETJSAMPLE() here */ - inptr += nc; + *outptr++ = *inptr; /* don't need GETJSAMPLE() here */ + inptr += nc; } } input_buf++; @@ -426,7 +441,7 @@ jinit_color_converter (j_compress_ptr cinfo) cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_color_converter)); + SIZEOF(my_color_converter)); cinfo->cconvert = &cconvert->pub; /* set start_pass to null method until we find out differently */ cconvert->pub.start_pass = null_method; @@ -439,11 +454,13 @@ jinit_color_converter (j_compress_ptr cinfo) break; case JCS_RGB: + case JCS_BG_RGB: if (cinfo->input_components != RGB_PIXELSIZE) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; case JCS_YCbCr: + case JCS_BG_YCC: if (cinfo->input_components != 3) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; @@ -460,8 +477,10 @@ jinit_color_converter (j_compress_ptr cinfo) break; } - /* Support color transform only for RGB colorspace */ - if (cinfo->color_transform && cinfo->jpeg_color_space != JCS_RGB) + /* Support color transform only for RGB colorspaces */ + if (cinfo->color_transform && + cinfo->jpeg_color_space != JCS_RGB && + cinfo->jpeg_color_space != JCS_BG_RGB) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); /* Check num_components, set conversion method based on requested space */ @@ -469,30 +488,35 @@ jinit_color_converter (j_compress_ptr cinfo) case JCS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_GRAYSCALE || - cinfo->in_color_space == JCS_YCbCr) + switch (cinfo->in_color_space) { + case JCS_GRAYSCALE: + case JCS_YCbCr: + case JCS_BG_YCC: cconvert->pub.color_convert = grayscale_convert; - else if (cinfo->in_color_space == JCS_RGB) { + break; + case JCS_RGB: cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = rgb_gray_convert; - } else + break; + default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } break; case JCS_RGB: + case JCS_BG_RGB: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB) { + if (cinfo->in_color_space == cinfo->jpeg_color_space) { switch (cinfo->color_transform) { case JCT_NONE: - cconvert->pub.color_convert = rgb_convert; - break; + cconvert->pub.color_convert = rgb_convert; + break; case JCT_SUBTRACT_GREEN: - cconvert->pub.color_convert = rgb_rgb1_convert; - break; + cconvert->pub.color_convert = rgb_rgb1_convert; + break; default: - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); @@ -501,13 +525,48 @@ jinit_color_converter (j_compress_ptr cinfo) case JCS_YCbCr: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_RGB) { + switch (cinfo->in_color_space) { + case JCS_RGB: cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = rgb_ycc_convert; - } else if (cinfo->in_color_space == JCS_YCbCr) + break; + case JCS_YCbCr: cconvert->pub.color_convert = null_convert; - else + break; + default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } + break; + + case JCS_BG_YCC: + if (cinfo->num_components != 3) + ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); + switch (cinfo->in_color_space) { + case JCS_RGB: + /* For conversion from normal RGB input to BG_YCC representation, + * the Cb/Cr values are first computed as usual, and then + * quantized further after DCT processing by a factor of + * 2 in reference to the nominal quantization factor. + */ + /* need quantization scale by factor of 2 after DCT */ + cinfo->comp_info[1].component_needed = TRUE; + cinfo->comp_info[2].component_needed = TRUE; + /* compute normal YCC first */ + cconvert->pub.start_pass = rgb_ycc_start; + cconvert->pub.color_convert = rgb_ycc_convert; + break; + case JCS_YCbCr: + /* need quantization scale by factor of 2 after DCT */ + cinfo->comp_info[1].component_needed = TRUE; + cinfo->comp_info[2].component_needed = TRUE; + /*FALLTHROUGH*/ + case JCS_BG_YCC: + /* Pass through for BG_YCC input */ + cconvert->pub.color_convert = null_convert; + break; + default: + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } break; case JCS_CMYK: @@ -522,18 +581,22 @@ jinit_color_converter (j_compress_ptr cinfo) case JCS_YCCK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); - if (cinfo->in_color_space == JCS_CMYK) { + switch (cinfo->in_color_space) { + case JCS_CMYK: cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = cmyk_ycck_convert; - } else if (cinfo->in_color_space == JCS_YCCK) + break; + case JCS_YCCK: cconvert->pub.color_convert = null_convert; - else + break; + default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } break; default: /* allow null conversion of JCS_UNKNOWN */ if (cinfo->jpeg_color_space != cinfo->in_color_space || - cinfo->num_components != cinfo->input_components) + cinfo->num_components != cinfo->input_components) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cconvert->pub.color_convert = null_convert; break; diff --git a/3rdparty/libjpeg/jcdctmgr.c b/3rdparty/libjpeg/jcdctmgr.c index ec90b9ae32..fafab91c69 100644 --- a/3rdparty/libjpeg/jcdctmgr.c +++ b/3rdparty/libjpeg/jcdctmgr.c @@ -2,6 +2,7 @@ * jcdctmgr.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2003-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -25,22 +26,30 @@ typedef struct { /* Pointer to the DCT routine actually in use */ forward_DCT_method_ptr do_dct[MAX_COMPONENTS]; - /* The actual post-DCT divisors --- not identical to the quant table - * entries, because of scaling (especially for an unnormalized DCT). - * Each table is given in normal array order. - */ - DCTELEM * divisors[NUM_QUANT_TBLS]; - #ifdef DCT_FLOAT_SUPPORTED /* Same as above for the floating-point case. */ float_DCT_method_ptr do_float_dct[MAX_COMPONENTS]; - FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; #endif } my_fdct_controller; typedef my_fdct_controller * my_fdct_ptr; +/* The allocated post-DCT divisor tables -- big enough for any + * supported variant and not identical to the quant table entries, + * because of scaling (especially for an unnormalized DCT) -- + * are pointed to by dct_table in the per-component comp_info + * structures. Each table is given in normal array order. + */ + +typedef union { + DCTELEM int_array[DCTSIZE2]; +#ifdef DCT_FLOAT_SUPPORTED + FAST_FLOAT float_array[DCTSIZE2]; +#endif +} divisor_table; + + /* The current scaled-DCT routines require ISLOW-style divisor tables, * so be sure to compile that code if either ISLOW or SCALING is requested. */ @@ -63,15 +72,15 @@ typedef my_fdct_controller * my_fdct_ptr; METHODDEF(void) forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks) + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) /* This version is used for integer DCT implementations. */ { /* This routine is heavily used, so it's worth coding it tightly. */ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; forward_DCT_method_ptr do_dct = fdct->do_dct[compptr->component_index]; - DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; + DCTELEM * divisors = (DCTELEM *) compptr->dct_table; DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; @@ -87,35 +96,35 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, register JCOEFPTR output_ptr = coef_blocks[bi]; for (i = 0; i < DCTSIZE2; i++) { - qval = divisors[i]; - temp = workspace[i]; - /* Divide the coefficient value by qval, ensuring proper rounding. - * Since C does not specify the direction of rounding for negative - * quotients, we have to force the dividend positive for portability. - * - * In most files, at least half of the output values will be zero - * (at default quantization settings, more like three-quarters...) - * so we should ensure that this case is fast. On many machines, - * a comparison is enough cheaper than a divide to make a special test - * a win. Since both inputs will be nonnegative, we need only test - * for a < b to discover whether a/b is 0. - * If your machine's division is fast enough, define FAST_DIVIDE. - */ + qval = divisors[i]; + temp = workspace[i]; + /* Divide the coefficient value by qval, ensuring proper rounding. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * + * In most files, at least half of the output values will be zero + * (at default quantization settings, more like three-quarters...) + * so we should ensure that this case is fast. On many machines, + * a comparison is enough cheaper than a divide to make a special test + * a win. Since both inputs will be nonnegative, we need only test + * for a < b to discover whether a/b is 0. + * If your machine's division is fast enough, define FAST_DIVIDE. + */ #ifdef FAST_DIVIDE #define DIVIDE_BY(a,b) a /= b #else #define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 #endif - if (temp < 0) { - temp = -temp; - temp += qval>>1; /* for rounding */ - DIVIDE_BY(temp, qval); - temp = -temp; - } else { - temp += qval>>1; /* for rounding */ - DIVIDE_BY(temp, qval); - } - output_ptr[i] = (JCOEF) temp; + if (temp < 0) { + temp = -temp; + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + temp = -temp; + } else { + temp += qval>>1; /* for rounding */ + DIVIDE_BY(temp, qval); + } + output_ptr[i] = (JCOEF) temp; } } } @@ -126,15 +135,15 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, METHODDEF(void) forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks) + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks) /* This version is used for floating-point DCT implementations. */ { /* This routine is heavily used, so it's worth coding it tightly. */ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; float_DCT_method_ptr do_dct = fdct->do_float_dct[compptr->component_index]; - FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; + FAST_FLOAT * divisors = (FAST_FLOAT *) compptr->dct_table; FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; @@ -150,15 +159,15 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, register JCOEFPTR output_ptr = coef_blocks[bi]; for (i = 0; i < DCTSIZE2; i++) { - /* Apply the quantization and scaling factor */ - temp = workspace[i] * divisors[i]; - /* Round to nearest integer. - * Since C does not specify the direction of rounding for negative - * quotients, we have to force the dividend positive for portability. - * The maximum coefficient size is +-16K (for 12-bit data), so this - * code should work for either 16-bit or 32-bit ints. - */ - output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); + /* Apply the quantization and scaling factor */ + temp = workspace[i] * divisors[i]; + /* Round to nearest integer. + * Since C does not specify the direction of rounding for negative + * quotients, we have to force the dividend positive for portability. + * The maximum coefficient size is +-16K (for 12-bit data), so this + * code should work for either 16-bit or 32-bit ints. + */ + output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); } } } @@ -320,54 +329,49 @@ start_pass_fdctmgr (j_compress_ptr cinfo) switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: - fdct->do_dct[ci] = jpeg_fdct_islow; - method = JDCT_ISLOW; - break; + fdct->do_dct[ci] = jpeg_fdct_islow; + method = JDCT_ISLOW; + break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: - fdct->do_dct[ci] = jpeg_fdct_ifast; - method = JDCT_IFAST; - break; + fdct->do_dct[ci] = jpeg_fdct_ifast; + method = JDCT_IFAST; + break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: - fdct->do_float_dct[ci] = jpeg_fdct_float; - method = JDCT_FLOAT; - break; + fdct->do_float_dct[ci] = jpeg_fdct_float; + method = JDCT_FLOAT; + break; #endif default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; } break; default: ERREXIT2(cinfo, JERR_BAD_DCTSIZE, - compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); + compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); break; } qtblno = compptr->quant_tbl_no; /* Make sure specified quantization table is present */ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) + cinfo->quant_tbl_ptrs[qtblno] == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); qtbl = cinfo->quant_tbl_ptrs[qtblno]; - /* Compute divisors for this quant table */ - /* We may do this more than once for same table, but it's not a big deal */ + /* Create divisor table from quant table */ switch (method) { #ifdef PROVIDE_ISLOW_TABLES case JDCT_ISLOW: /* For LL&M IDCT method, divisors are equal to raw quantization * coefficients multiplied by 8 (to counteract scaling). */ - if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; + dtbl = (DCTELEM *) compptr->dct_table; for (i = 0; i < DCTSIZE2; i++) { - dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; + dtbl[i] = + ((DCTELEM) qtbl->quantval[i]) << (compptr->component_needed ? 4 : 3); } fdct->pub.forward_DCT[ci] = forward_DCT; break; @@ -375,38 +379,33 @@ start_pass_fdctmgr (j_compress_ptr cinfo) #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: { - /* For AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - */ + /* For AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + */ #define CONST_BITS 14 - static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 - }; - SHIFT_TEMPS + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS - if (fdct->divisors[qtblno] == NULL) { - fdct->divisors[qtblno] = (DCTELEM *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(DCTELEM)); - } - dtbl = fdct->divisors[qtblno]; - for (i = 0; i < DCTSIZE2; i++) { - dtbl[i] = (DCTELEM) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], - (INT32) aanscales[i]), - CONST_BITS-3); - } + dtbl = (DCTELEM *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + dtbl[i] = (DCTELEM) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + compptr->component_needed ? CONST_BITS-4 : CONST_BITS-3); + } } fdct->pub.forward_DCT[ci] = forward_DCT; break; @@ -414,36 +413,31 @@ start_pass_fdctmgr (j_compress_ptr cinfo) #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: { - /* For float AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - * What's actually stored is 1/divisor so that the inner loop can - * use a multiplication rather than a division. - */ - FAST_FLOAT * fdtbl; - int row, col; - static const double aanscalefactor[DCTSIZE] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; + /* For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + FAST_FLOAT * fdtbl = (FAST_FLOAT *) compptr->dct_table; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; - if (fdct->float_divisors[qtblno] == NULL) { - fdct->float_divisors[qtblno] = (FAST_FLOAT *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - DCTSIZE2 * SIZEOF(FAST_FLOAT)); - } - fdtbl = fdct->float_divisors[qtblno]; - i = 0; - for (row = 0; row < DCTSIZE; row++) { - for (col = 0; col < DCTSIZE; col++) { - fdtbl[i] = (FAST_FLOAT) - (1.0 / (((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col] * 8.0))); - i++; - } - } + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fdtbl[i] = (FAST_FLOAT) + (1.0 / ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * + (compptr->component_needed ? 16.0 : 8.0))); + i++; + } + } } fdct->pub.forward_DCT[ci] = forward_DCT_float; break; @@ -464,19 +458,20 @@ GLOBAL(void) jinit_forward_dct (j_compress_ptr cinfo) { my_fdct_ptr fdct; - int i; + int ci; + jpeg_component_info *compptr; fdct = (my_fdct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_fdct_controller)); - cinfo->fdct = (struct jpeg_forward_dct *) fdct; + SIZEOF(my_fdct_controller)); + cinfo->fdct = &fdct->pub; fdct->pub.start_pass = start_pass_fdctmgr; - /* Mark divisor tables unallocated */ - for (i = 0; i < NUM_QUANT_TBLS; i++) { - fdct->divisors[i] = NULL; -#ifdef DCT_FLOAT_SUPPORTED - fdct->float_divisors[i] = NULL; -#endif + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + /* Allocate a divisor table for each component */ + compptr->dct_table = + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(divisor_table)); } } diff --git a/3rdparty/libjpeg/jchuff.c b/3rdparty/libjpeg/jchuff.c index b705af1858..d1313f676f 100644 --- a/3rdparty/libjpeg/jchuff.c +++ b/3rdparty/libjpeg/jchuff.c @@ -2,7 +2,7 @@ * jchuff.c * * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2006-2009 by Guido Vollbeding. + * Modified 2006-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -68,12 +68,12 @@ typedef struct { #else #if MAX_COMPS_IN_SCAN == 4 #define ASSIGN_STATE(dest,src) \ - ((dest).put_buffer = (src).put_buffer, \ - (dest).put_bits = (src).put_bits, \ - (dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) + ((dest).put_buffer = (src).put_buffer, \ + (dest).put_bits = (src).put_bits, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) #endif #endif @@ -143,9 +143,9 @@ typedef struct { #ifdef RIGHT_SHIFT_IS_UNSIGNED #define ISHIFT_TEMPS int ishift_temp; #define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ - (ishift_temp >> (shft))) + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ + (ishift_temp >> (shft))) #else #define ISHIFT_TEMPS #define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) @@ -159,7 +159,7 @@ typedef struct { LOCAL(void) jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, - c_derived_tbl ** pdtbl) + c_derived_tbl ** pdtbl) { JHUFF_TBL *htbl; c_derived_tbl *dtbl; @@ -184,9 +184,9 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, if (*pdtbl == NULL) *pdtbl = (c_derived_tbl *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(c_derived_tbl)); + SIZEOF(c_derived_tbl)); dtbl = *pdtbl; - + /* Figure C.1: make table of Huffman code length for each symbol */ p = 0; @@ -199,7 +199,7 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, } huffsize[p] = 0; lastp = p; - + /* Figure C.2: generate the codes themselves */ /* We also validate that the counts represent a legal Huffman code tree. */ @@ -219,7 +219,7 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, code <<= 1; si++; } - + /* Figure C.3: generate encoding tables */ /* These are code and size indexed by symbol value */ @@ -253,16 +253,16 @@ jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, /* Emit a byte, taking 'action' if must suspend. */ #define emit_byte_s(state,val,action) \ - { *(state)->next_output_byte++ = (JOCTET) (val); \ - if (--(state)->free_in_buffer == 0) \ - if (! dump_buffer_s(state)) \ - { action; } } + { *(state)->next_output_byte++ = (JOCTET) (val); \ + if (--(state)->free_in_buffer == 0) \ + if (! dump_buffer_s(state)) \ + { action; } } /* Emit a byte */ #define emit_byte_e(entropy,val) \ - { *(entropy)->next_output_byte++ = (JOCTET) (val); \ - if (--(entropy)->free_in_buffer == 0) \ - dump_buffer_e(entropy); } + { *(entropy)->next_output_byte++ = (JOCTET) (val); \ + if (--(entropy)->free_in_buffer == 0) \ + dump_buffer_e(entropy); } LOCAL(boolean) @@ -308,20 +308,23 @@ emit_bits_s (working_state * state, unsigned int code, int size) /* Emit some bits; return TRUE if successful, FALSE if must suspend */ { /* This routine is heavily used, so it's worth coding tightly. */ - register INT32 put_buffer = (INT32) code; - register int put_bits = state->cur.put_bits; + register INT32 put_buffer; + register int put_bits; /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); - put_buffer &= (((INT32) 1)<cur.put_bits; put_buffer <<= 24 - put_bits; /* align incoming bits */ - put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */ + /* and merge with old buffer contents */ + put_buffer |= state->cur.put_buffer; while (put_bits >= 8) { int c = (int) ((put_buffer >> 16) & 0xFF); @@ -347,8 +350,8 @@ emit_bits_e (huff_entropy_ptr entropy, unsigned int code, int size) /* Emit some bits, unless we are in gather mode */ { /* This routine is heavily used, so it's worth coding tightly. */ - register INT32 put_buffer = (INT32) code; - register int put_bits = entropy->saved.put_bits; + register INT32 put_buffer; + register int put_bits; /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) @@ -357,9 +360,11 @@ emit_bits_e (huff_entropy_ptr entropy, unsigned int code, int size) if (entropy->gather_statistics) return; /* do nothing if we're only getting stats */ - put_buffer &= (((INT32) 1)<saved.put_bits; put_buffer <<= 24 - put_bits; /* align incoming bits */ @@ -438,7 +443,7 @@ emit_ac_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) LOCAL(void) emit_buffered_bits (huff_entropy_ptr entropy, char * bufstart, - unsigned int nbits) + unsigned int nbits) { if (entropy->gather_statistics) return; /* no real work */ @@ -543,10 +548,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; register int temp, temp2; register int nbits; - int blkn, ci; - int Al = cinfo->Al; - JBLOCKROW block; - jpeg_component_info * compptr; + int blkn, ci, tbl; ISHIFT_TEMPS entropy->next_output_byte = cinfo->dest->next_output_byte; @@ -559,21 +561,20 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; ci = cinfo->MCU_membership[blkn]; - compptr = cinfo->cur_comp_info[ci]; + tbl = cinfo->cur_comp_info[ci]->dc_tbl_no; /* Compute the DC value after the required point transform by Al. * This is simply an arithmetic right shift. */ - temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); + temp = IRIGHT_SHIFT((int) (MCU_data[blkn][0][0]), cinfo->Al); /* DC differences are figured on the point-transformed values. */ - temp = temp2 - entropy->saved.last_dc_val[ci]; - entropy->saved.last_dc_val[ci] = temp2; + temp2 = temp - entropy->saved.last_dc_val[ci]; + entropy->saved.last_dc_val[ci] = temp; /* Encode the DC coefficient difference per section G.1.2.1 */ - temp2 = temp; + temp = temp2; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative input, want temp2 = bitwise complement of abs(input) */ @@ -594,7 +595,7 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count/emit the Huffman-coded symbol for the number of bits */ - emit_dc_symbol(entropy, compptr->dc_tbl_no, nbits); + emit_dc_symbol(entropy, tbl, nbits); /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ @@ -628,12 +629,12 @@ METHODDEF(boolean) encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + const int * natural_order; + JBLOCKROW block; register int temp, temp2; register int nbits; register int r, k; int Se, Al; - const int * natural_order; - JBLOCKROW block; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; @@ -651,9 +652,9 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) block = MCU_data[0]; /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ - + r = 0; /* r = run length of zeros */ - + for (k = cinfo->Ss; k <= Se; k++) { if ((temp = (*block)[natural_order[k]]) == 0) { r++; @@ -731,18 +732,15 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* * MCU encoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. + * Note: we assume such scans can be multi-component, + * although the spec is not very clear on the point. */ METHODDEF(boolean) encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - register int temp; - int blkn; - int Al = cinfo->Al; - JBLOCKROW block; + int Al, blkn; entropy->next_output_byte = cinfo->dest->next_output_byte; entropy->free_in_buffer = cinfo->dest->free_in_buffer; @@ -752,13 +750,12 @@ encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) if (entropy->restarts_to_go == 0) emit_restart_e(entropy, entropy->next_restart_num); + Al = cinfo->Al; + /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - /* We simply emit the Al'th bit of the DC coefficient value. */ - temp = (*block)[0]; - emit_bits_e(entropy, (unsigned int) (temp >> Al), 1); + emit_bits_e(entropy, (unsigned int) (MCU_data[blkn][0][0] >> Al), 1); } cinfo->dest->next_output_byte = entropy->next_output_byte; @@ -786,14 +783,14 @@ METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + const int * natural_order; + JBLOCKROW block; register int temp; register int r, k; + int Se, Al; int EOB; char *BR_buffer; unsigned int BR; - int Se, Al; - const int * natural_order; - JBLOCKROW block; int absvalues[DCTSIZE2]; entropy->next_output_byte = cinfo->dest->next_output_byte; @@ -830,7 +827,7 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) } /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ - + r = 0; /* r = run length of zeros */ BR = 0; /* BR = count of buffered bits added now */ BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ @@ -914,11 +911,11 @@ encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) LOCAL(boolean) encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, - c_derived_tbl *dctbl, c_derived_tbl *actbl) + c_derived_tbl *dctbl, c_derived_tbl *actbl) { register int temp, temp2; register int nbits; - register int k, r, i; + register int r, k; int Se = state->cinfo->lim_Se; const int * natural_order = state->cinfo->natural_order; @@ -960,40 +957,40 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, r = 0; /* r = run length of zeros */ for (k = 1; k <= Se; k++) { - if ((temp = block[natural_order[k]]) == 0) { + if ((temp2 = block[natural_order[k]]) == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { - if (! emit_bits_s(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) - return FALSE; - r -= 16; + if (! emit_bits_s(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) + return FALSE; + r -= 16; } - temp2 = temp; + temp = temp2; if (temp < 0) { - temp = -temp; /* temp is abs value of input */ - /* This code assumes we are on a two's complement machine */ - temp2--; + temp = -temp; /* temp is abs value of input */ + /* This code assumes we are on a two's complement machine */ + temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* there must be at least one 1 bit */ while ((temp >>= 1)) - nbits++; + nbits++; /* Check for out-of-range coefficient values */ if (nbits > MAX_COEF_BITS) - ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); + ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); /* Emit Huffman symbol for run length / number of bits */ - i = (r << 4) + nbits; - if (! emit_bits_s(state, actbl->ehufco[i], actbl->ehufsi[i])) - return FALSE; + temp = (r << 4) + nbits; + if (! emit_bits_s(state, actbl->ehufco[temp], actbl->ehufsi[temp])) + return FALSE; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (! emit_bits_s(state, (unsigned int) temp2, nbits)) - return FALSE; + return FALSE; r = 0; } @@ -1030,7 +1027,7 @@ encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! emit_restart_s(&state, entropy->next_restart_num)) - return FALSE; + return FALSE; } /* Encode the MCU data blocks */ @@ -1038,9 +1035,9 @@ encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; if (! encode_one_block(&state, - MCU_data[blkn][0], state.cur.last_dc_val[ci], - entropy->dc_derived_tbls[compptr->dc_tbl_no], - entropy->ac_derived_tbls[compptr->ac_tbl_no])) + MCU_data[blkn][0], state.cur.last_dc_val[ci], + entropy->dc_derived_tbls[compptr->dc_tbl_no], + entropy->ac_derived_tbls[compptr->ac_tbl_no])) return FALSE; /* Update last_dc_val */ state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; @@ -1120,11 +1117,11 @@ finish_pass_huff (j_compress_ptr cinfo) LOCAL(void) htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, - long dc_counts[], long ac_counts[]) + long dc_counts[], long ac_counts[]) { register int temp; register int nbits; - register int k, r; + register int r, k; int Se = cinfo->lim_Se; const int * natural_order = cinfo->natural_order; @@ -1159,21 +1156,21 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { - ac_counts[0xF0]++; - r -= 16; + ac_counts[0xF0]++; + r -= 16; } /* Find the number of bits needed for the magnitude of the coefficient */ if (temp < 0) - temp = -temp; + temp = -temp; /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* there must be at least one 1 bit */ while ((temp >>= 1)) - nbits++; + nbits++; /* Check for out-of-range coefficient values */ if (nbits > MAX_COEF_BITS) - ERREXIT(cinfo, JERR_BAD_DCT_COEF); + ERREXIT(cinfo, JERR_BAD_DCT_COEF); /* Count Huffman symbol for run length / number of bits */ ac_counts[(r << 4) + nbits]++; @@ -1205,7 +1202,7 @@ encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) if (entropy->restarts_to_go == 0) { /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) - entropy->saved.last_dc_val[ci] = 0; + entropy->saved.last_dc_val[ci] = 0; /* Update restart state */ entropy->restarts_to_go = cinfo->restart_interval; } @@ -1216,8 +1213,8 @@ encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], - entropy->dc_count_ptrs[compptr->dc_tbl_no], - entropy->ac_count_ptrs[compptr->ac_tbl_no]); + entropy->dc_count_ptrs[compptr->dc_tbl_no], + entropy->ac_count_ptrs[compptr->ac_tbl_no]); entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; } @@ -1269,7 +1266,7 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) MEMZERO(codesize, SIZEOF(codesize)); for (i = 0; i < 257; i++) others[i] = -1; /* init links to empty */ - + freq[256] = 1; /* make sure 256 has a nonzero count */ /* Including the pseudo-symbol 256 in the Huffman procedure guarantees * that no real symbol is given code-value of all ones, because 256 @@ -1285,8 +1282,8 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v) { - v = freq[i]; - c1 = i; + v = freq[i]; + c1 = i; } } @@ -1296,15 +1293,15 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v && i != c1) { - v = freq[i]; - c2 = i; + v = freq[i]; + c2 = i; } } /* Done if we've merged everything into one frequency */ if (c2 < 0) break; - + /* Else merge the two counts/trees */ freq[c1] += freq[c2]; freq[c2] = 0; @@ -1315,9 +1312,9 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) c1 = others[c1]; codesize[c1]++; } - + others[c1] = c2; /* chain c2 onto c1's tree branch */ - + /* Increment the codesize of everything in c2's tree branch */ codesize[c2]++; while (others[c2] >= 0) { @@ -1332,7 +1329,7 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) /* The JPEG standard seems to think that this can't happen, */ /* but I'm paranoid... */ if (codesize[i] > MAX_CLEN) - ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); + ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); bits[codesize[i]]++; } @@ -1348,13 +1345,13 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) * shortest nonzero BITS entry is converted into a prefix for two code words * one bit longer. */ - + for (i = MAX_CLEN; i > 16; i--) { while (bits[i] > 0) { j = i - 2; /* find length of new prefix to be used */ while (bits[j] == 0) - j--; - + j--; + bits[i] -= 2; /* remove two symbols */ bits[i-1]++; /* one goes in this length */ bits[j+1] += 2; /* two new symbols in this length */ @@ -1366,10 +1363,10 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) while (bits[i] == 0) /* find largest codelength still in use */ i--; bits[i]--; - + /* Return final symbol counts (only for lengths 0..16) */ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); - + /* Return a list of the symbols sorted by code length */ /* It's not real clear to me why we don't need to consider the codelength * changes made above, but the JPEG spec seems to think this works. @@ -1378,8 +1375,8 @@ jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) for (i = 1; i <= MAX_CLEN; i++) { for (j = 0; j <= 255; j++) { if (codesize[j] == i) { - htbl->huffval[p] = (UINT8) j; - p++; + htbl->huffval[p] = (UINT8) j; + p++; } } } @@ -1419,22 +1416,22 @@ finish_pass_gather (j_compress_ptr cinfo) if (cinfo->Ss == 0 && cinfo->Ah == 0) { tbl = compptr->dc_tbl_no; if (! did_dc[tbl]) { - htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[tbl]); - did_dc[tbl] = TRUE; + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[tbl]); + did_dc[tbl] = TRUE; } } /* AC needs no table when not present */ if (cinfo->Se) { tbl = compptr->ac_tbl_no; if (! did_ac[tbl]) { - htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[tbl]); - did_ac[tbl] = TRUE; + htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[tbl]); + did_ac[tbl] = TRUE; } } } @@ -1468,19 +1465,19 @@ start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) /* Select execution routine */ if (cinfo->Ah == 0) { if (cinfo->Ss == 0) - entropy->pub.encode_mcu = encode_mcu_DC_first; + entropy->pub.encode_mcu = encode_mcu_DC_first; else - entropy->pub.encode_mcu = encode_mcu_AC_first; + entropy->pub.encode_mcu = encode_mcu_AC_first; } else { if (cinfo->Ss == 0) - entropy->pub.encode_mcu = encode_mcu_DC_refine; + entropy->pub.encode_mcu = encode_mcu_DC_refine; else { - entropy->pub.encode_mcu = encode_mcu_AC_refine; - /* AC refinement needs a correction bit buffer */ - if (entropy->bit_buffer == NULL) - entropy->bit_buffer = (char *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - MAX_CORR_BITS * SIZEOF(char)); + entropy->pub.encode_mcu = encode_mcu_AC_refine; + /* AC refinement needs a correction bit buffer */ + if (entropy->bit_buffer == NULL) + entropy->bit_buffer = (char *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(char)); } } @@ -1501,22 +1498,22 @@ start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) if (cinfo->Ss == 0 && cinfo->Ah == 0) { tbl = compptr->dc_tbl_no; if (gather_statistics) { - /* Check for invalid table index */ - /* (make_c_derived_tbl does this in the other path) */ - if (tbl < 0 || tbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); - /* Allocate and zero the statistics tables */ - /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ - if (entropy->dc_count_ptrs[tbl] == NULL) - entropy->dc_count_ptrs[tbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->dc_count_ptrs[tbl], 257 * SIZEOF(long)); + /* Check for invalid table index */ + /* (make_c_derived_tbl does this in the other path) */ + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + /* Allocate and zero the statistics tables */ + /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ + if (entropy->dc_count_ptrs[tbl] == NULL) + entropy->dc_count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[tbl], 257 * SIZEOF(long)); } else { - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - jpeg_make_c_derived_tbl(cinfo, TRUE, tbl, - & entropy->dc_derived_tbls[tbl]); + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + jpeg_make_c_derived_tbl(cinfo, TRUE, tbl, + & entropy->dc_derived_tbls[tbl]); } /* Initialize DC predictions to 0 */ entropy->saved.last_dc_val[ci] = 0; @@ -1525,16 +1522,16 @@ start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) if (cinfo->Se) { tbl = compptr->ac_tbl_no; if (gather_statistics) { - if (tbl < 0 || tbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); - if (entropy->ac_count_ptrs[tbl] == NULL) - entropy->ac_count_ptrs[tbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->ac_count_ptrs[tbl], 257 * SIZEOF(long)); + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + if (entropy->ac_count_ptrs[tbl] == NULL) + entropy->ac_count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[tbl], 257 * SIZEOF(long)); } else { - jpeg_make_c_derived_tbl(cinfo, FALSE, tbl, - & entropy->ac_derived_tbls[tbl]); + jpeg_make_c_derived_tbl(cinfo, FALSE, tbl, + & entropy->ac_derived_tbls[tbl]); } } } @@ -1561,8 +1558,8 @@ jinit_huff_encoder (j_compress_ptr cinfo) entropy = (huff_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(huff_entropy_encoder)); - cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; + SIZEOF(huff_entropy_encoder)); + cinfo->entropy = &entropy->pub; entropy->pub.start_pass = start_pass_huff; /* Mark tables unallocated */ diff --git a/3rdparty/libjpeg/jcinit.c b/3rdparty/libjpeg/jcinit.c index d4f5e3a7a8..1e13e3462d 100644 --- a/3rdparty/libjpeg/jcinit.c +++ b/3rdparty/libjpeg/jcinit.c @@ -2,6 +2,7 @@ * jcinit.c * * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2003-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -29,6 +30,24 @@ GLOBAL(void) jinit_compress_master (j_compress_ptr cinfo) { + long samplesperrow; + JDIMENSION jd_samplesperrow; + + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + + /* Sanity check on image dimensions */ + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || + cinfo->input_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + + /* Width of an input scanline must be representable as JDIMENSION. */ + samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; + jd_samplesperrow = (JDIMENSION) samplesperrow; + if ((long) jd_samplesperrow != samplesperrow) + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + /* Initialize master control (includes parameter checking/processing) */ jinit_c_master_control(cinfo, FALSE /* full compression */); @@ -49,7 +68,7 @@ jinit_compress_master (j_compress_ptr cinfo) /* Need a full-image coefficient buffer in any multi-pass mode. */ jinit_c_coef_controller(cinfo, - (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); + (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); jinit_marker_writer(cinfo); diff --git a/3rdparty/libjpeg/jcmainct.c b/3rdparty/libjpeg/jcmainct.c index 897b737321..39b97902e8 100644 --- a/3rdparty/libjpeg/jcmainct.c +++ b/3rdparty/libjpeg/jcmainct.c @@ -53,12 +53,12 @@ typedef my_main_controller * my_main_ptr; /* Forward declarations */ METHODDEF(void) process_data_simple_main - JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); #ifdef FULL_MAIN_BUFFER_SUPPORTED METHODDEF(void) process_data_buffer_main - JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); + JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); #endif @@ -112,8 +112,8 @@ start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) METHODDEF(void) process_data_simple_main (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail) + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) { my_main_ptr mainp = (my_main_ptr) cinfo->main; @@ -121,9 +121,9 @@ process_data_simple_main (j_compress_ptr cinfo, /* Read input data if we haven't filled the main buffer yet */ if (mainp->rowgroup_ctr < (JDIMENSION) cinfo->min_DCT_v_scaled_size) (*cinfo->prep->pre_process_data) (cinfo, - input_buf, in_row_ctr, in_rows_avail, - mainp->buffer, &mainp->rowgroup_ctr, - (JDIMENSION) cinfo->min_DCT_v_scaled_size); + input_buf, in_row_ctr, in_rows_avail, + mainp->buffer, &mainp->rowgroup_ctr, + (JDIMENSION) cinfo->min_DCT_v_scaled_size); /* If we don't have a full iMCU row buffered, return to application for * more data. Note that preprocessor will always pad to fill the iMCU row @@ -141,8 +141,8 @@ process_data_simple_main (j_compress_ptr cinfo, * think we were done. */ if (! mainp->suspended) { - (*in_row_ctr)--; - mainp->suspended = TRUE; + (*in_row_ctr)--; + mainp->suspended = TRUE; } return; } @@ -168,8 +168,8 @@ process_data_simple_main (j_compress_ptr cinfo, METHODDEF(void) process_data_buffer_main (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail) + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail) { my_main_ptr mainp = (my_main_ptr) cinfo->main; int ci; @@ -180,18 +180,18 @@ process_data_buffer_main (j_compress_ptr cinfo, /* Realign the virtual buffers if at the start of an iMCU row. */ if (mainp->rowgroup_ctr == 0) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - mainp->buffer[ci] = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, mainp->whole_image[ci], mainp->cur_iMCU_row * - ((JDIMENSION) (compptr->v_samp_factor * cinfo->min_DCT_v_scaled_size)), - (JDIMENSION) (compptr->v_samp_factor * cinfo->min_DCT_v_scaled_size), - writing); + ci++, compptr++) { + mainp->buffer[ci] = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, mainp->whole_image[ci], mainp->cur_iMCU_row * + ((JDIMENSION) (compptr->v_samp_factor * cinfo->min_DCT_v_scaled_size)), + (JDIMENSION) (compptr->v_samp_factor * cinfo->min_DCT_v_scaled_size), + writing); } /* In a read pass, pretend we just read some source data. */ if (! writing) { - *in_row_ctr += (JDIMENSION) - (cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size); - mainp->rowgroup_ctr = (JDIMENSION) cinfo->min_DCT_v_scaled_size; + *in_row_ctr += (JDIMENSION) + (cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size); + mainp->rowgroup_ctr = (JDIMENSION) cinfo->min_DCT_v_scaled_size; } } @@ -199,35 +199,35 @@ process_data_buffer_main (j_compress_ptr cinfo, /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ if (writing) { (*cinfo->prep->pre_process_data) (cinfo, - input_buf, in_row_ctr, in_rows_avail, - mainp->buffer, &mainp->rowgroup_ctr, - (JDIMENSION) cinfo->min_DCT_v_scaled_size); + input_buf, in_row_ctr, in_rows_avail, + mainp->buffer, &mainp->rowgroup_ctr, + (JDIMENSION) cinfo->min_DCT_v_scaled_size); /* Return to application if we need more data to fill the iMCU row. */ if (mainp->rowgroup_ctr < (JDIMENSION) cinfo->min_DCT_v_scaled_size) - return; + return; } /* Emit data, unless this is a sink-only pass. */ if (mainp->pass_mode != JBUF_SAVE_SOURCE) { if (! (*cinfo->coef->compress_data) (cinfo, mainp->buffer)) { - /* If compressor did not consume the whole row, then we must need to - * suspend processing and return to the application. In this situation - * we pretend we didn't yet consume the last input row; otherwise, if - * it happened to be the last row of the image, the application would - * think we were done. - */ - if (! mainp->suspended) { - (*in_row_ctr)--; - mainp->suspended = TRUE; - } - return; + /* If compressor did not consume the whole row, then we must need to + * suspend processing and return to the application. In this situation + * we pretend we didn't yet consume the last input row; otherwise, if + * it happened to be the last row of the image, the application would + * think we were done. + */ + if (! mainp->suspended) { + (*in_row_ctr)--; + mainp->suspended = TRUE; + } + return; } /* We did finish the row. Undo our little suspension hack if a previous * call suspended; then mark the main buffer empty. */ if (mainp->suspended) { - (*in_row_ctr)++; - mainp->suspended = FALSE; + (*in_row_ctr)++; + mainp->suspended = FALSE; } } @@ -253,7 +253,7 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) mainp = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_main_controller)); + SIZEOF(my_main_controller)); cinfo->main = &mainp->pub; mainp->pub.start_pass = start_pass_main; @@ -269,14 +269,14 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) /* Allocate a full-image virtual array for each component */ /* Note we pad the bottom to a multiple of the iMCU height */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { + ci++, compptr++) { mainp->whole_image[ci] = (*cinfo->mem->request_virt_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - compptr->width_in_blocks * ((JDIMENSION) compptr->DCT_h_scaled_size), - ((JDIMENSION) jround_up((long) compptr->height_in_blocks, - (long) compptr->v_samp_factor)) * - ((JDIMENSION) cinfo->min_DCT_v_scaled_size), - (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + compptr->width_in_blocks * ((JDIMENSION) compptr->DCT_h_scaled_size), + ((JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor)) * + ((JDIMENSION) cinfo->min_DCT_v_scaled_size), + (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); @@ -287,11 +287,11 @@ jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) #endif /* Allocate a strip buffer for each component */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { + ci++, compptr++) { mainp->buffer[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - compptr->width_in_blocks * ((JDIMENSION) compptr->DCT_h_scaled_size), - (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); + ((j_common_ptr) cinfo, JPOOL_IMAGE, + compptr->width_in_blocks * ((JDIMENSION) compptr->DCT_h_scaled_size), + (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size)); } } } diff --git a/3rdparty/libjpeg/jcmarker.c b/3rdparty/libjpeg/jcmarker.c index 711a3b28f9..ca2bb39922 100644 --- a/3rdparty/libjpeg/jcmarker.c +++ b/3rdparty/libjpeg/jcmarker.c @@ -2,7 +2,7 @@ * jcmarker.c * * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2003-2012 by Guido Vollbeding. + * Modified 2003-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -172,7 +172,7 @@ emit_dqt (j_compress_ptr cinfo, int index) /* The table entries must be emitted in zigzag order. */ unsigned int qval = qtbl->quantval[cinfo->natural_order[i]]; if (prec) - emit_byte(cinfo, (int) (qval >> 8)); + emit_byte(cinfo, (int) (qval >> 8)); emit_byte(cinfo, (int) (qval & 0xFF)); } @@ -189,7 +189,7 @@ emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) { JHUFF_TBL * htbl; int length, i; - + if (is_ac) { htbl = cinfo->ac_huff_tbl_ptrs[index]; index += 0x10; /* output index has AC bit set */ @@ -199,23 +199,23 @@ emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) if (htbl == NULL) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); - + if (! htbl->sent_table) { emit_marker(cinfo, M_DHT); - + length = 0; for (i = 1; i <= 16; i++) length += htbl->bits[i]; - + emit_2bytes(cinfo, length + 2 + 1 + 16); emit_byte(cinfo, index); - + for (i = 1; i <= 16; i++) emit_byte(cinfo, htbl->bits[i]); - + for (i = 0; i < length; i++) emit_byte(cinfo, htbl->huffval[i]); - + htbl->sent_table = TRUE; } } @@ -257,12 +257,12 @@ emit_dac (j_compress_ptr cinfo) for (i = 0; i < NUM_ARITH_TBLS; i++) { if (dc_in_use[i]) { - emit_byte(cinfo, i); - emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); } if (ac_in_use[i]) { - emit_byte(cinfo, i + 0x10); - emit_byte(cinfo, cinfo->arith_ac_K[i]); + emit_byte(cinfo, i + 0x10); + emit_byte(cinfo, cinfo->arith_ac_K[i]); } } } @@ -275,7 +275,7 @@ emit_dri (j_compress_ptr cinfo) /* Emit a DRI marker */ { emit_marker(cinfo, M_DRI); - + emit_2bytes(cinfo, 4); /* fixed length */ emit_2bytes(cinfo, (int) cinfo->restart_interval); @@ -292,7 +292,7 @@ emit_lse_ict (j_compress_ptr cinfo) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); emit_marker(cinfo, M_JPG8); - + emit_2bytes(cinfo, 24); /* fixed length */ emit_byte(cinfo, 0x0D); /* ID inverse transform specification */ @@ -319,9 +319,9 @@ emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) { int ci; jpeg_component_info *compptr; - + emit_marker(cinfo, code); - + emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ /* Make sure image isn't bigger than SOF field can handle */ @@ -350,13 +350,13 @@ emit_sos (j_compress_ptr cinfo) { int i, td, ta; jpeg_component_info *compptr; - + emit_marker(cinfo, M_SOS); - + emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ - + emit_byte(cinfo, cinfo->comps_in_scan); - + for (i = 0; i < cinfo->comps_in_scan; i++) { compptr = cinfo->cur_comp_info[i]; emit_byte(cinfo, compptr->component_id); @@ -384,9 +384,9 @@ emit_pseudo_sos (j_compress_ptr cinfo) /* Emit a pseudo SOS marker */ { emit_marker(cinfo, M_SOS); - + emit_2bytes(cinfo, 2 + 1 + 3); /* length */ - + emit_byte(cinfo, 0); /* Ns */ emit_byte(cinfo, 0); /* Ss */ @@ -410,9 +410,9 @@ emit_jfif_app0 (j_compress_ptr cinfo) * Thumbnail X size (1 byte) * Thumbnail Y size (1 byte) */ - + emit_marker(cinfo, M_APP0); - + emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ @@ -449,9 +449,9 @@ emit_adobe_app14 (j_compress_ptr cinfo) * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with * whether the encoder performed a transformation, which is pretty useless. */ - + emit_marker(cinfo, M_APP14); - + emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ @@ -508,8 +508,8 @@ write_marker_byte (j_compress_ptr cinfo, int val) * Write datastream header. * This consists of an SOI and optional APPn markers. * We recommend use of the JFIF marker, but not the Adobe marker, - * when using YCbCr or grayscale data. The JFIF marker should NOT - * be used for any other JPEG colorspace. The Adobe marker is helpful + * when using YCbCr or grayscale data. The JFIF marker is also used + * for other standard JPEG colorspaces. The Adobe marker is helpful * to distinguish RGB, CMYK, and YCCK colorspaces. * Note that an application can write additional header markers after * jpeg_start_compress returns. @@ -547,7 +547,7 @@ write_frame_header (j_compress_ptr cinfo) int ci, prec; boolean is_baseline; jpeg_component_info *compptr; - + /* Emit DQT for each quantization table. * Note that emit_dqt() suppresses any duplicate tables. */ @@ -567,9 +567,9 @@ write_frame_header (j_compress_ptr cinfo) } else { is_baseline = TRUE; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { + ci++, compptr++) { if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) - is_baseline = FALSE; + is_baseline = FALSE; } if (prec && is_baseline) { is_baseline = FALSE; @@ -630,10 +630,10 @@ write_scan_header (j_compress_ptr cinfo) compptr = cinfo->cur_comp_info[i]; /* DC needs no table for refinement scan */ if (cinfo->Ss == 0 && cinfo->Ah == 0) - emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); /* AC needs no table when not present */ if (cinfo->Se) - emit_dht(cinfo, compptr->ac_tbl_no, TRUE); + emit_dht(cinfo, compptr->ac_tbl_no, TRUE); } } @@ -682,9 +682,9 @@ write_tables_only (j_compress_ptr cinfo) if (! cinfo->arith_code) { for (i = 0; i < NUM_HUFF_TBLS; i++) { if (cinfo->dc_huff_tbl_ptrs[i] != NULL) - emit_dht(cinfo, i, FALSE); + emit_dht(cinfo, i, FALSE); if (cinfo->ac_huff_tbl_ptrs[i] != NULL) - emit_dht(cinfo, i, TRUE); + emit_dht(cinfo, i, TRUE); } } @@ -704,7 +704,7 @@ jinit_marker_writer (j_compress_ptr cinfo) /* Create the subobject */ marker = (my_marker_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_marker_writer)); + SIZEOF(my_marker_writer)); cinfo->marker = &marker->pub; /* Initialize method pointers */ marker->pub.write_file_header = write_file_header; diff --git a/3rdparty/libjpeg/jcmaster.c b/3rdparty/libjpeg/jcmaster.c index a34865d002..2a8ae63303 100644 --- a/3rdparty/libjpeg/jcmaster.c +++ b/3rdparty/libjpeg/jcmaster.c @@ -2,13 +2,13 @@ * jcmaster.c * * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2003-2011 by Guido Vollbeding. + * Modified 2003-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains master control logic for the JPEG compressor. * These routines are concerned with parameter validation, initial setup, - * and inter-pass control (determining the number of passes and the work + * and inter-pass control (determining the number of passes and the work * to be done in each pass). */ @@ -20,9 +20,9 @@ /* Private state */ typedef enum { - main_pass, /* input data, also do first output step */ - huff_opt_pass, /* Huffman code optimization pass */ - output_pass /* data output pass */ + main_pass, /* input data, also do first output step */ + huff_opt_pass, /* Huffman code optimization pass */ + output_pass /* data output pass */ } c_pass_type; typedef struct { @@ -210,7 +210,7 @@ jpeg_calc_trans_dimensions (j_compress_ptr cinfo) { if (cinfo->min_DCT_h_scaled_size != cinfo->min_DCT_v_scaled_size) ERREXIT2(cinfo, JERR_BAD_DCTSIZE, - cinfo->min_DCT_h_scaled_size, cinfo->min_DCT_v_scaled_size); + cinfo->min_DCT_h_scaled_size, cinfo->min_DCT_v_scaled_size); cinfo->block_size = cinfo->min_DCT_h_scaled_size; } @@ -222,8 +222,6 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) { int ci, ssize; jpeg_component_info *compptr; - long samplesperrow; - JDIMENSION jd_samplesperrow; if (transcode_only) jpeg_calc_trans_dimensions(cinfo); @@ -251,7 +249,7 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) /* Sanity check on image dimensions */ if (cinfo->jpeg_height <= 0 || cinfo->jpeg_width <= 0 || - cinfo->num_components <= 0 || cinfo->input_components <= 0) + cinfo->num_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); /* Make sure image isn't bigger than I can handle */ @@ -259,20 +257,14 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) (long) cinfo->jpeg_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - /* Width of an input scanline must be representable as JDIMENSION. */ - samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; - jd_samplesperrow = (JDIMENSION) samplesperrow; - if ((long) jd_samplesperrow != samplesperrow) - ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); - - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) + /* Only 8 to 12 bits data precision are supported for DCT based JPEG */ + if (cinfo->data_precision < 8 || cinfo->data_precision > 12) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); + MAX_COMPONENTS); /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; @@ -280,12 +272,12 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || - compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo, JERR_BAD_SAMPLING); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, - compptr->h_samp_factor); + compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, - compptr->v_samp_factor); + compptr->v_samp_factor); } /* Compute dimensions of components */ @@ -301,8 +293,8 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) ssize = 1; #ifdef DCT_SCALING_SUPPORTED while (cinfo->min_DCT_h_scaled_size * ssize <= - (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && - (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { + (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { ssize = ssize * 2; } #endif @@ -310,8 +302,8 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) ssize = 1; #ifdef DCT_SCALING_SUPPORTED while (cinfo->min_DCT_v_scaled_size * ssize <= - (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && - (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { + (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { ssize = ssize * 2; } #endif @@ -319,28 +311,30 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) /* We don't support DCT ratios larger than 2. */ if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) - compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) - compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; + compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_width * - (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), - (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_height * - (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); - /* Mark component needed (this flag isn't actually used for compression) */ - compptr->component_needed = TRUE; + (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + /* Don't need quantization scale after DCT, + * until color conversion says otherwise. + */ + compptr->component_needed = FALSE; } /* Compute number of fully interleaved MCU rows (number of times that @@ -348,7 +342,7 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_height, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); } @@ -381,15 +375,15 @@ validate_script (j_compress_ptr cinfo) #ifdef C_PROGRESSIVE_SUPPORTED cinfo->progressive_mode = TRUE; last_bitpos_ptr = & last_bitpos[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) + for (ci = 0; ci < cinfo->num_components; ci++) for (coefi = 0; coefi < DCTSIZE2; coefi++) - *last_bitpos_ptr++ = -1; + *last_bitpos_ptr++ = -1; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { cinfo->progressive_mode = FALSE; - for (ci = 0; ci < cinfo->num_components; ci++) + for (ci = 0; ci < cinfo->num_components; ci++) component_sent[ci] = FALSE; } @@ -401,10 +395,10 @@ validate_script (j_compress_ptr cinfo) for (ci = 0; ci < ncomps; ci++) { thisi = scanptr->component_index[ci]; if (thisi < 0 || thisi >= cinfo->num_components) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); /* Components must appear in SOF order within each scan */ if (ci > 0 && thisi <= scanptr->component_index[ci-1]) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); } /* Validate progression parameters */ Ss = scanptr->Ss; @@ -426,43 +420,43 @@ validate_script (j_compress_ptr cinfo) #define MAX_AH_AL 13 #endif if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || - Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); if (Ss == 0) { - if (Se != 0) /* DC and AC together not OK */ - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (Se != 0) /* DC and AC together not OK */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } else { - if (ncomps != 1) /* AC scans must be for only one component */ - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + if (ncomps != 1) /* AC scans must be for only one component */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); } for (ci = 0; ci < ncomps; ci++) { - last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; - if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - for (coefi = Ss; coefi <= Se; coefi++) { - if (last_bitpos_ptr[coefi] < 0) { - /* first scan of this coefficient */ - if (Ah != 0) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } else { - /* not first scan */ - if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); - } - last_bitpos_ptr[coefi] = Al; - } + last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; + if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + for (coefi = Ss; coefi <= Se; coefi++) { + if (last_bitpos_ptr[coefi] < 0) { + /* first scan of this coefficient */ + if (Ah != 0) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } else { + /* not first scan */ + if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + } + last_bitpos_ptr[coefi] = Al; + } } #endif } else { /* For sequential JPEG, all progression parameters must be these: */ if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) - ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); + ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); /* Make sure components are not sent twice */ for (ci = 0; ci < ncomps; ci++) { - thisi = scanptr->component_index[ci]; - if (component_sent[thisi]) - ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); - component_sent[thisi] = TRUE; + thisi = scanptr->component_index[ci]; + if (component_sent[thisi]) + ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] = TRUE; } } } @@ -477,13 +471,13 @@ validate_script (j_compress_ptr cinfo) */ for (ci = 0; ci < cinfo->num_components; ci++) { if (last_bitpos[ci][0] < 0) - ERREXIT(cinfo, JERR_MISSING_DATA); + ERREXIT(cinfo, JERR_MISSING_DATA); } #endif } else { for (ci = 0; ci < cinfo->num_components; ci++) { if (! component_sent[ci]) - ERREXIT(cinfo, JERR_MISSING_DATA); + ERREXIT(cinfo, JERR_MISSING_DATA); } } } @@ -539,7 +533,7 @@ select_scan_parameters (j_compress_ptr cinfo) cinfo->comps_in_scan = scanptr->comps_in_scan; for (ci = 0; ci < scanptr->comps_in_scan; ci++) { cinfo->cur_comp_info[ci] = - &cinfo->comp_info[scanptr->component_index[ci]]; + &cinfo->comp_info[scanptr->component_index[ci]]; } if (cinfo->progressive_mode) { cinfo->Ss = scanptr->Ss; @@ -555,7 +549,7 @@ select_scan_parameters (j_compress_ptr cinfo) /* Prepare for single sequential-JPEG scan containing all components */ if (cinfo->num_components > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPS_IN_SCAN); + MAX_COMPS_IN_SCAN); cinfo->comps_in_scan = cinfo->num_components; for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; @@ -575,16 +569,16 @@ per_scan_setup (j_compress_ptr cinfo) { int ci, mcublks, tmp; jpeg_component_info *compptr; - + if (cinfo->comps_in_scan == 1) { - + /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; - + /* Overall image size in MCUs */ cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - + /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; @@ -597,28 +591,28 @@ per_scan_setup (j_compress_ptr cinfo) tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (tmp == 0) tmp = compptr->v_samp_factor; compptr->last_row_height = tmp; - + /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; - + } else { - + /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, - MAX_COMPS_IN_SCAN); - + MAX_COMPS_IN_SCAN); + /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_width, - (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long) cinfo->jpeg_height, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); - + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + cinfo->blocks_in_MCU = 0; - + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Sampling factors give # of blocks of component in each MCU */ @@ -636,12 +630,12 @@ per_scan_setup (j_compress_ptr cinfo) /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) - ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); while (mcublks-- > 0) { - cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } - + } /* Convert restart specified in rows to actual MCU count. */ @@ -681,8 +675,8 @@ prepare_for_pass (j_compress_ptr cinfo) (*cinfo->fdct->start_pass) (cinfo); (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); (*cinfo->coef->start_pass) (cinfo, - (master->total_passes > 1 ? - JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (master->total_passes > 1 ? + JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); if (cinfo->optimize_coding) { /* No immediate data output; postpone writing frame/scan headers */ @@ -810,8 +804,8 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) master = (my_master_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_comp_master)); - cinfo->master = (struct jpeg_comp_master *) master; + SIZEOF(my_comp_master)); + cinfo->master = &master->pub; master->pub.prepare_for_pass = prepare_for_pass; master->pub.pass_startup = pass_startup; master->pub.finish_pass = finish_pass_master; @@ -833,10 +827,14 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) cinfo->num_scans = 1; } - if ((cinfo->progressive_mode || cinfo->block_size < DCTSIZE) && - !cinfo->arith_code) /* TEMPORARY HACK ??? */ - /* assume default tables no good for progressive or downscale mode */ - cinfo->optimize_coding = TRUE; + if (cinfo->optimize_coding) + cinfo->arith_code = FALSE; /* disable arithmetic coding */ + else if (! cinfo->arith_code && + (cinfo->progressive_mode || + (cinfo->block_size > 1 && cinfo->block_size < DCTSIZE))) + /* TEMPORARY HACK ??? */ + /* assume default tables no good for progressive or reduced AC mode */ + cinfo->optimize_coding = TRUE; /* force Huffman optimization */ /* Initialize my private state */ if (transcode_only) { diff --git a/3rdparty/libjpeg/jconfig.h b/3rdparty/libjpeg/jconfig.h index 7f8e27104f..e9d33e5870 100644 --- a/3rdparty/libjpeg/jconfig.h +++ b/3rdparty/libjpeg/jconfig.h @@ -1,136 +1,52 @@ +/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 9x or NT. */ +/* This file also works for Borland C++ 32-bit (bcc32) on Windows 9x or NT. */ +/* see jconfig.txt for explanations */ + #define HAVE_PROTOTYPES #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT - -/* Define this if an ordinary "char" type is unsigned. - * If you're not sure, leaving it undefined will work at some cost in speed. - * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. - */ +/* #define void char */ +/* #define const */ #undef CHAR_IS_UNSIGNED - -#if defined __MINGW__ || defined __MINGW32__ || (!defined WIN32 && !defined _WIN32) -/* Define this if your system has an ANSI-conforming file. - */ #define HAVE_STDDEF_H - -/* Define this if your system has an ANSI-conforming file. - */ #define HAVE_STDLIB_H -#endif - -/* Define this if your system does not have an ANSI/SysV , - * but does have a BSD-style . - */ #undef NEED_BSD_STRINGS - -/* Define this if your system does not provide typedef size_t in any of the - * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in - * instead. - */ #undef NEED_SYS_TYPES_H - -/* For 80x86 machines, you need to define NEED_FAR_POINTERS, - * unless you are using a large-data memory model or 80386 flat-memory mode. - * On less brain-damaged CPUs this symbol must not be defined. - * (Defining this symbol causes large data structures to be referenced through - * "far" pointers and to be allocated with a special version of malloc.) - */ -#undef NEED_FAR_POINTERS - -/* Define this if your linker needs global names to be unique in less - * than the first 15 characters. - */ +#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */ #undef NEED_SHORT_EXTERNAL_NAMES - -/* Although a real ANSI C compiler can deal perfectly well with pointers to - * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI - * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, - * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you - * actually get "missing structure definition" warnings or errors while - * compiling the JPEG code. - */ #undef INCOMPLETE_TYPES_BROKEN -/* Define "boolean" as unsigned char, not int, on Windows systems. - */ -#ifdef _WIN32 +/* Define "boolean" as unsigned char, not enum, per Windows custom */ #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ typedef unsigned char boolean; #endif -#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ +#ifndef FALSE /* in case these macros already exist */ +#define FALSE 0 /* values of boolean */ #endif +#ifndef TRUE +#define TRUE 1 +#endif +#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ -/* - * The following options affect code selection within the JPEG library, - * but they don't need to be visible to applications using the library. - * To minimize application namespace pollution, the symbols won't be - * defined unless JPEG_INTERNALS has been defined. - */ - #ifdef JPEG_INTERNALS -/* Define this if your compiler implements ">>" on signed values as a logical - * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, - * which is the normal and rational definition. - */ #undef RIGHT_SHIFT_IS_UNSIGNED -/* These are for configuring the JPEG memory manager. */ -#define DEFAULT_MAX_MEM 1073741824 /*1Gb*/ - -#if !defined WIN32 && !defined _WIN32 -#define INLINE __inline__ -#undef NO_MKTEMP -#endif - #endif /* JPEG_INTERNALS */ - -/* - * The remaining options do not affect the JPEG library proper, - * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). - * Other applications can ignore these. - */ - #ifdef JPEG_CJPEG_DJPEG -/* These defines indicate which image (non-JPEG) file formats are allowed. */ - #define BMP_SUPPORTED /* BMP image file format */ #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ -/* Define this if you want to name both input and output files on the command - * line, rather than using stdout and optionally stdin. You MUST do this if - * your system can't cope with binary I/O to stdin/stdout. See comments at - * head of cjpeg.c or djpeg.c. - */ -#if defined WIN32 || defined _WIN32 #define TWO_FILE_COMMANDLINE /* optional */ #define USE_SETMODE /* Microsoft has setmode() */ -#else -#undef TWO_FILE_COMMANDLINE -#endif - -/* Define this if your system needs explicit cleanup of temporary files. - * This is crucial under MS-DOS, where the temporary "files" may be areas - * of extended memory; on most other systems it's not as important. - */ #undef NEED_SIGNAL_CATCHER - -/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). - * This is necessary on systems that distinguish text files from binary files, - * and is harmless on most systems that don't. If you have one of the rare - * systems that complains about the "b" spec, define this symbol. - */ #undef DONT_USE_B_MODE - -/* Define this if you want percent-done progress reports from cjpeg/djpeg. - */ -#undef PROGRESS_REPORT - +#undef PROGRESS_REPORT /* optional */ #endif /* JPEG_CJPEG_DJPEG */ diff --git a/3rdparty/libjpeg/jcparam.c b/3rdparty/libjpeg/jcparam.c index a99a0d4292..4b2bee2497 100644 --- a/3rdparty/libjpeg/jcparam.c +++ b/3rdparty/libjpeg/jcparam.c @@ -2,7 +2,7 @@ * jcparam.c * * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2003-2012 by Guido Vollbeding. + * Modified 2003-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -22,8 +22,8 @@ GLOBAL(void) jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, boolean force_baseline) + const unsigned int *basic_table, + int scale_factor, boolean force_baseline) /* Define a quantization table equal to the basic_table times * a scale factor (given as a percentage). * If force_baseline is TRUE, the computed quantization table entries @@ -96,15 +96,15 @@ jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline) { /* Set up two quantization tables using the specified scaling */ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, - cinfo->q_scale_factor[0], force_baseline); + cinfo->q_scale_factor[0], force_baseline); jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, - cinfo->q_scale_factor[1], force_baseline); + cinfo->q_scale_factor[1], force_baseline); } GLOBAL(void) jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, - boolean force_baseline) + boolean force_baseline) /* Set or change the 'quality' (quantization) setting, using default tables * and a straight percentage-scaling quality scale. In most cases it's better * to use jpeg_set_quality (below); this entry point is provided for @@ -113,9 +113,9 @@ jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, { /* Set up two quantization tables using the specified scaling */ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, - scale_factor, force_baseline); + scale_factor, force_baseline); jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, - scale_factor, force_baseline); + scale_factor, force_baseline); } @@ -167,7 +167,7 @@ jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) LOCAL(void) add_huff_table (j_compress_ptr cinfo, - JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) + JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) /* Define a Huffman table */ { int nsymbols, len; @@ -204,12 +204,12 @@ std_huff_tables (j_compress_ptr cinfo) { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_luminance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - + static const UINT8 bits_dc_chrominance[17] = { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_chrominance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - + static const UINT8 bits_ac_luminance[17] = { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; static const UINT8 val_ac_luminance[] = @@ -234,7 +234,7 @@ std_huff_tables (j_compress_ptr cinfo) 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; - + static const UINT8 bits_ac_chrominance[17] = { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; static const UINT8 val_ac_chrominance[] = @@ -259,15 +259,15 @@ std_huff_tables (j_compress_ptr cinfo) 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; - + add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], - bits_dc_luminance, val_dc_luminance); + bits_dc_luminance, val_dc_luminance); add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], - bits_ac_luminance, val_ac_luminance); + bits_ac_luminance, val_ac_luminance); add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], - bits_dc_chrominance, val_dc_chrominance); + bits_dc_chrominance, val_dc_chrominance); add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], - bits_ac_chrominance, val_ac_chrominance); + bits_ac_chrominance, val_ac_chrominance); } @@ -297,7 +297,7 @@ jpeg_set_defaults (j_compress_ptr cinfo) if (cinfo->comp_info == NULL) cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - MAX_COMPONENTS * SIZEOF(jpeg_component_info)); + MAX_COMPONENTS * SIZEOF(jpeg_component_info)); /* Initialize everything not dependent on the color space */ @@ -323,18 +323,17 @@ jpeg_set_defaults (j_compress_ptr cinfo) /* Expect normal source image, not raw downsampled data */ cinfo->raw_data_in = FALSE; - /* Use Huffman coding, not arithmetic coding, by default */ - cinfo->arith_code = FALSE; + /* The standard Huffman tables are only valid for 8-bit data precision. + * If the precision is higher, use arithmetic coding. + * (Alternatively, using Huffman coding would be possible with forcing + * optimization on so that usable tables will be computed, or by + * supplying default tables that are valid for the desired precision.) + * Otherwise, use Huffman coding by default. + */ + cinfo->arith_code = cinfo->data_precision > 8 ? TRUE : FALSE; /* By default, don't do extra passes to optimize entropy coding */ cinfo->optimize_coding = FALSE; - /* The standard Huffman tables are only valid for 8-bit data precision. - * If the precision is higher, force optimization on so that usable - * tables will be computed. This test can be removed if default tables - * are supplied that are valid for the desired precision. - */ - if (cinfo->data_precision > 8) - cinfo->optimize_coding = TRUE; /* By default, use the simpler non-cosited sampling alignment */ cinfo->CCIR601_sampling = FALSE; @@ -360,6 +359,9 @@ jpeg_set_defaults (j_compress_ptr cinfo) * JFIF_minor_version to 2. We could probably get away with just defaulting * to 1.02, but there may still be some decoders in use that will complain * about that; saying 1.01 should minimize compatibility problems. + * + * For wide gamut colorspaces (BG_RGB and BG_YCC), the major version will be + * overridden by jpeg_set_colorspace and set to 2. */ cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ cinfo->JFIF_minor_version = 1; @@ -384,6 +386,9 @@ GLOBAL(void) jpeg_default_colorspace (j_compress_ptr cinfo) { switch (cinfo->in_color_space) { + case JCS_UNKNOWN: + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + break; case JCS_GRAYSCALE: jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); break; @@ -399,8 +404,12 @@ jpeg_default_colorspace (j_compress_ptr cinfo) case JCS_YCCK: jpeg_set_colorspace(cinfo, JCS_YCCK); break; - case JCS_UNKNOWN: - jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + case JCS_BG_RGB: + /* No translation for now -- conversion to BG_YCC not yet supportet */ + jpeg_set_colorspace(cinfo, JCS_BG_RGB); + break; + case JCS_BG_YCC: + jpeg_set_colorspace(cinfo, JCS_BG_YCC); break; default: ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); @@ -441,29 +450,40 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ switch (colorspace) { + case JCS_UNKNOWN: + cinfo->num_components = cinfo->input_components; + if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) + ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, + MAX_COMPONENTS); + for (ci = 0; ci < cinfo->num_components; ci++) { + SET_COMP(ci, ci, 1,1, 0, 0,0); + } + break; case JCS_GRAYSCALE: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 1; /* JFIF specifies component ID 1 */ - SET_COMP(0, 1, 1,1, 0, 0,0); + SET_COMP(0, 0x01, 1,1, 0, 0,0); break; case JCS_RGB: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ cinfo->num_components = 3; - SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); - SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, - cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, - cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); - SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); + SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); + SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); + SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); break; case JCS_YCbCr: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 3; /* JFIF specifies component IDs 1,2,3 */ /* We default to 2x2 subsamples of chrominance */ - SET_COMP(0, 1, 2,2, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(0, 0x01, 2,2, 0, 0,0); + SET_COMP(1, 0x02, 1,1, 1, 1,1); + SET_COMP(2, 0x03, 1,1, 1, 1,1); break; case JCS_CMYK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ @@ -476,19 +496,33 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) case JCS_YCCK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ cinfo->num_components = 4; - SET_COMP(0, 1, 2,2, 0, 0,0); - SET_COMP(1, 2, 1,1, 1, 1,1); - SET_COMP(2, 3, 1,1, 1, 1,1); - SET_COMP(3, 4, 2,2, 0, 0,0); + SET_COMP(0, 0x01, 2,2, 0, 0,0); + SET_COMP(1, 0x02, 1,1, 1, 1,1); + SET_COMP(2, 0x03, 1,1, 1, 1,1); + SET_COMP(3, 0x04, 2,2, 0, 0,0); break; - case JCS_UNKNOWN: - cinfo->num_components = cinfo->input_components; - if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) - ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); - for (ci = 0; ci < cinfo->num_components; ci++) { - SET_COMP(ci, ci, 1,1, 0, 0,0); - } + case JCS_BG_RGB: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->JFIF_major_version = 2; /* Set JFIF major version = 2 */ + cinfo->num_components = 3; + /* Add offset 0x20 to the normal R/G/B component IDs */ + SET_COMP(0, 0x72 /* 'r' */, 1,1, 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); + SET_COMP(1, 0x67 /* 'g' */, 1,1, 0, 0,0); + SET_COMP(2, 0x62 /* 'b' */, 1,1, 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0, + cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0); + break; + case JCS_BG_YCC: + cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ + cinfo->JFIF_major_version = 2; /* Set JFIF major version = 2 */ + cinfo->num_components = 3; + /* Add offset 0x20 to the normal Cb/Cr component IDs */ + /* We default to 2x2 subsamples of chrominance */ + SET_COMP(0, 0x01, 2,2, 0, 0,0); + SET_COMP(1, 0x22, 1,1, 1, 1,1); + SET_COMP(2, 0x23, 1,1, 1, 1,1); break; default: ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); @@ -500,7 +534,7 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) LOCAL(jpeg_scan_info *) fill_a_scan (jpeg_scan_info * scanptr, int ci, - int Ss, int Se, int Ah, int Al) + int Ss, int Se, int Ah, int Al) /* Support routine: generate one scan for specified component */ { scanptr->comps_in_scan = 1; @@ -515,7 +549,7 @@ fill_a_scan (jpeg_scan_info * scanptr, int ci, LOCAL(jpeg_scan_info *) fill_scans (jpeg_scan_info * scanptr, int ncomps, - int Ss, int Se, int Ah, int Al) + int Ss, int Se, int Ah, int Al) /* Support routine: generate one scan for each component */ { int ci; @@ -572,8 +606,10 @@ jpeg_simple_progression (j_compress_ptr cinfo) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Figure space needed for script. Calculation must match code below! */ - if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { - /* Custom script for YCbCr color images. */ + if (ncomps == 3 && + (cinfo->jpeg_color_space == JCS_YCbCr || + cinfo->jpeg_color_space == JCS_BG_YCC)) { + /* Custom script for YCC color images. */ nscans = 10; } else { /* All-purpose script for other color spaces. */ @@ -588,20 +624,22 @@ jpeg_simple_progression (j_compress_ptr cinfo) * multiple compressions without changing the settings. To avoid a memory * leak if jpeg_simple_progression is called repeatedly for the same JPEG * object, we try to re-use previously allocated space, and we allocate - * enough space to handle YCbCr even if initially asked for grayscale. + * enough space to handle YCC even if initially asked for grayscale. */ if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { cinfo->script_space_size = MAX(nscans, 10); cinfo->script_space = (jpeg_scan_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - cinfo->script_space_size * SIZEOF(jpeg_scan_info)); + cinfo->script_space_size * SIZEOF(jpeg_scan_info)); } scanptr = cinfo->script_space; cinfo->scan_info = scanptr; cinfo->num_scans = nscans; - if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { - /* Custom script for YCbCr color images. */ + if (ncomps == 3 && + (cinfo->jpeg_color_space == JCS_YCbCr || + cinfo->jpeg_color_space == JCS_BG_YCC)) { + /* Custom script for YCC color images. */ /* Initial DC scan */ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); /* Initial AC scan: get some luma data out in a hurry */ diff --git a/3rdparty/libjpeg/jcprepct.c b/3rdparty/libjpeg/jcprepct.c index 1b4e14e46a..be44cc4b45 100644 --- a/3rdparty/libjpeg/jcprepct.c +++ b/3rdparty/libjpeg/jcprepct.c @@ -104,13 +104,13 @@ start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) LOCAL(void) expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, - int input_rows, int output_rows) + int input_rows, int output_rows) { register int row; for (row = input_rows; row < output_rows; row++) { jcopy_sample_rows(image_data, input_rows-1, image_data, row, - 1, num_cols); + 1, num_cols); } } @@ -126,10 +126,10 @@ expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, METHODDEF(void) pre_process_data (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail) + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; int numrows, ci; @@ -137,32 +137,32 @@ pre_process_data (j_compress_ptr cinfo, jpeg_component_info * compptr; while (*in_row_ctr < in_rows_avail && - *out_row_group_ctr < out_row_groups_avail) { + *out_row_group_ctr < out_row_groups_avail) { /* Do color conversion to fill the conversion buffer. */ inrows = in_rows_avail - *in_row_ctr; numrows = cinfo->max_v_samp_factor - prep->next_buf_row; numrows = (int) MIN((JDIMENSION) numrows, inrows); (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, - prep->color_buf, - (JDIMENSION) prep->next_buf_row, - numrows); + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); *in_row_ctr += numrows; prep->next_buf_row += numrows; prep->rows_to_go -= numrows; /* If at bottom of image, pad to fill the conversion buffer. */ if (prep->rows_to_go == 0 && - prep->next_buf_row < cinfo->max_v_samp_factor) { + prep->next_buf_row < cinfo->max_v_samp_factor) { for (ci = 0; ci < cinfo->num_components; ci++) { - expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, - prep->next_buf_row, cinfo->max_v_samp_factor); + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, cinfo->max_v_samp_factor); } prep->next_buf_row = cinfo->max_v_samp_factor; } /* If we've filled the conversion buffer, empty it. */ if (prep->next_buf_row == cinfo->max_v_samp_factor) { (*cinfo->downsample->downsample) (cinfo, - prep->color_buf, (JDIMENSION) 0, - output_buf, *out_row_group_ctr); + prep->color_buf, (JDIMENSION) 0, + output_buf, *out_row_group_ctr); prep->next_buf_row = 0; (*out_row_group_ctr)++; } @@ -170,15 +170,15 @@ pre_process_data (j_compress_ptr cinfo, * Note we assume the caller is providing a one-iMCU-height output buffer! */ if (prep->rows_to_go == 0 && - *out_row_group_ctr < out_row_groups_avail) { + *out_row_group_ctr < out_row_groups_avail) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - numrows = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / - cinfo->min_DCT_v_scaled_size; - expand_bottom_edge(output_buf[ci], - compptr->width_in_blocks * compptr->DCT_h_scaled_size, - (int) (*out_row_group_ctr * numrows), - (int) (out_row_groups_avail * numrows)); + ci++, compptr++) { + numrows = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / + cinfo->min_DCT_v_scaled_size; + expand_bottom_edge(output_buf[ci], + compptr->width_in_blocks * compptr->DCT_h_scaled_size, + (int) (*out_row_group_ctr * numrows), + (int) (out_row_groups_avail * numrows)); } *out_row_group_ctr = out_row_groups_avail; break; /* can exit outer loop without test */ @@ -195,10 +195,10 @@ pre_process_data (j_compress_ptr cinfo, METHODDEF(void) pre_process_context (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail) + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; int numrows, ci; @@ -212,19 +212,19 @@ pre_process_context (j_compress_ptr cinfo, numrows = prep->next_buf_stop - prep->next_buf_row; numrows = (int) MIN((JDIMENSION) numrows, inrows); (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, - prep->color_buf, - (JDIMENSION) prep->next_buf_row, - numrows); + prep->color_buf, + (JDIMENSION) prep->next_buf_row, + numrows); /* Pad at top of image, if first time through */ if (prep->rows_to_go == cinfo->image_height) { - for (ci = 0; ci < cinfo->num_components; ci++) { - int row; - for (row = 1; row <= cinfo->max_v_samp_factor; row++) { - jcopy_sample_rows(prep->color_buf[ci], 0, - prep->color_buf[ci], -row, - 1, cinfo->image_width); - } - } + for (ci = 0; ci < cinfo->num_components; ci++) { + int row; + for (row = 1; row <= cinfo->max_v_samp_factor; row++) { + jcopy_sample_rows(prep->color_buf[ci], 0, + prep->color_buf[ci], -row, + 1, cinfo->image_width); + } + } } *in_row_ctr += numrows; prep->next_buf_row += numrows; @@ -232,29 +232,29 @@ pre_process_context (j_compress_ptr cinfo, } else { /* Return for more data, unless we are at the bottom of the image. */ if (prep->rows_to_go != 0) - break; + break; /* When at bottom of image, pad to fill the conversion buffer. */ if (prep->next_buf_row < prep->next_buf_stop) { - for (ci = 0; ci < cinfo->num_components; ci++) { - expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, - prep->next_buf_row, prep->next_buf_stop); - } - prep->next_buf_row = prep->next_buf_stop; + for (ci = 0; ci < cinfo->num_components; ci++) { + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, + prep->next_buf_row, prep->next_buf_stop); + } + prep->next_buf_row = prep->next_buf_stop; } } /* If we've gotten enough data, downsample a row group. */ if (prep->next_buf_row == prep->next_buf_stop) { (*cinfo->downsample->downsample) (cinfo, - prep->color_buf, - (JDIMENSION) prep->this_row_group, - output_buf, *out_row_group_ctr); + prep->color_buf, + (JDIMENSION) prep->this_row_group, + output_buf, *out_row_group_ctr); (*out_row_group_ctr)++; /* Advance pointers with wraparound as necessary. */ prep->this_row_group += cinfo->max_v_samp_factor; if (prep->this_row_group >= buf_height) - prep->this_row_group = 0; + prep->this_row_group = 0; if (prep->next_buf_row >= buf_height) - prep->next_buf_row = 0; + prep->next_buf_row = 0; prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; } } @@ -279,8 +279,8 @@ create_context_buffer (j_compress_ptr cinfo) */ fake_buffer = (JSAMPARRAY) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (cinfo->num_components * 5 * rgroup_height) * - SIZEOF(JSAMPROW)); + (cinfo->num_components * 5 * rgroup_height) * + SIZEOF(JSAMPROW)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { @@ -291,12 +291,12 @@ create_context_buffer (j_compress_ptr cinfo) true_buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) (((long) compptr->width_in_blocks * - cinfo->min_DCT_h_scaled_size * - cinfo->max_h_samp_factor) / compptr->h_samp_factor), + cinfo->min_DCT_h_scaled_size * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION) (3 * rgroup_height)); /* Copy true buffer row pointers into the middle of the fake row array */ MEMCOPY(fake_buffer + rgroup_height, true_buffer, - 3 * rgroup_height * SIZEOF(JSAMPROW)); + 3 * rgroup_height * SIZEOF(JSAMPROW)); /* Fill in the above and below wraparound pointers */ for (i = 0; i < rgroup_height; i++) { fake_buffer[i] = true_buffer[2 * rgroup_height + i]; @@ -326,7 +326,7 @@ jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) prep = (my_prep_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_prep_controller)); + SIZEOF(my_prep_controller)); cinfo->prep = (struct jpeg_c_prep_controller *) prep; prep->pub.start_pass = start_pass_prep; @@ -346,13 +346,13 @@ jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) /* No context, just make it tall enough for one row group */ prep->pub.pre_process_data = pre_process_data; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { + ci++, compptr++) { prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) (((long) compptr->width_in_blocks * - cinfo->min_DCT_h_scaled_size * - cinfo->max_h_samp_factor) / compptr->h_samp_factor), - (JDIMENSION) cinfo->max_v_samp_factor); + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) (((long) compptr->width_in_blocks * + cinfo->min_DCT_h_scaled_size * + cinfo->max_h_samp_factor) / compptr->h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); } } } diff --git a/3rdparty/libjpeg/jcsample.c b/3rdparty/libjpeg/jcsample.c index 306bfd5b35..4d36f85f35 100644 --- a/3rdparty/libjpeg/jcsample.c +++ b/3rdparty/libjpeg/jcsample.c @@ -52,8 +52,8 @@ /* Pointer to routine to downsample a single component */ typedef JMETHOD(void, downsample1_ptr, - (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data)); + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY output_data)); /* Private subobject */ @@ -94,7 +94,7 @@ start_pass_downsample (j_compress_ptr cinfo) LOCAL(void) expand_right_edge (JSAMPARRAY image_data, int num_rows, - JDIMENSION input_cols, JDIMENSION output_cols) + JDIMENSION input_cols, JDIMENSION output_cols) { register JSAMPROW ptr; register JSAMPLE pixval; @@ -107,7 +107,7 @@ expand_right_edge (JSAMPARRAY image_data, int num_rows, ptr = image_data[row] + input_cols; pixval = ptr[-1]; /* don't need GETJSAMPLE() here */ for (count = numcols; count > 0; count--) - *ptr++ = pixval; + *ptr++ = pixval; } } } @@ -121,8 +121,8 @@ expand_right_edge (JSAMPARRAY image_data, int num_rows, METHODDEF(void) sep_downsample (j_compress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_index, - JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) { my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; int ci; @@ -133,7 +133,7 @@ sep_downsample (j_compress_ptr cinfo, ci++, compptr++) { in_ptr = input_buf[ci] + in_row_index; out_ptr = output_buf[ci] + - (out_row_group_index * downsample->rowgroup_height[ci]); + (out_row_group_index * downsample->rowgroup_height[ci]); (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); } } @@ -148,7 +148,7 @@ sep_downsample (j_compress_ptr cinfo, METHODDEF(void) int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + JSAMPARRAY input_data, JSAMPARRAY output_data) { my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; @@ -167,19 +167,19 @@ int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * h_expand); + cinfo->image_width, output_cols * h_expand); inrow = outrow = 0; while (inrow < cinfo->max_v_samp_factor) { outptr = output_data[outrow]; for (outcol = 0, outcol_h = 0; outcol < output_cols; - outcol++, outcol_h += h_expand) { + outcol++, outcol_h += h_expand) { outvalue = 0; for (v = 0; v < v_expand; v++) { - inptr = input_data[inrow+v] + outcol_h; - for (h = 0; h < h_expand; h++) { - outvalue += (INT32) GETJSAMPLE(*inptr++); - } + inptr = input_data[inrow+v] + outcol_h; + for (h = 0; h < h_expand; h++) { + outvalue += (INT32) GETJSAMPLE(*inptr++); + } } *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); } @@ -197,14 +197,14 @@ int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, METHODDEF(void) fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + JSAMPARRAY input_data, JSAMPARRAY output_data) { /* Copy the data */ jcopy_sample_rows(input_data, 0, output_data, 0, - cinfo->max_v_samp_factor, cinfo->image_width); + cinfo->max_v_samp_factor, cinfo->image_width); /* Edge-expand */ expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width, - compptr->width_in_blocks * compptr->DCT_h_scaled_size); + compptr->width_in_blocks * compptr->DCT_h_scaled_size); } @@ -222,7 +222,7 @@ fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, METHODDEF(void) h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow; JDIMENSION outcol; @@ -235,7 +235,7 @@ h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * 2); + cinfo->image_width, output_cols * 2); for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { outptr = output_data[inrow]; @@ -243,7 +243,7 @@ h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, bias = 0; /* bias = 0,1,0,1,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) - + bias) >> 1); + + bias) >> 1); bias ^= 1; /* 0=>1, 1=>0 */ inptr += 2; } @@ -259,7 +259,7 @@ h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, METHODDEF(void) h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION outcol; @@ -272,7 +272,7 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, - cinfo->image_width, output_cols * 2); + cinfo->image_width, output_cols * 2); inrow = outrow = 0; while (inrow < cinfo->max_v_samp_factor) { @@ -282,8 +282,8 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, bias = 1; /* bias = 1,2,1,2,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) - + bias) >> 2); + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + + bias) >> 2); bias ^= 3; /* 1=>2, 2=>1 */ inptr0 += 2; inptr1 += 2; } @@ -303,7 +303,7 @@ h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, METHODDEF(void) h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION colctr; @@ -316,7 +316,7 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, * efficient. */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, - cinfo->image_width, output_cols * 2); + cinfo->image_width, output_cols * 2); /* We don't bother to form the individual "smoothed" input pixel values; * we can directly compute the output which is the average of the four @@ -344,14 +344,14 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, /* Special case for first column: pretend column -1 is same as column 0 */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + - GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); neighsum += neighsum; neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; @@ -359,17 +359,17 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, for (colctr = output_cols - 2; colctr > 0; colctr--) { /* sum of pixels directly mapped to this output element */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); /* sum of edge-neighbor pixels */ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + - GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + - GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); /* The edge-neighbors count twice as much as corner-neighbors */ neighsum += neighsum; /* Add in the corner-neighbors */ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + - GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); /* form final output scaled up by 2^16 */ membersum = membersum * memberscale + neighsum * neighscale; /* round, descale and output it */ @@ -379,14 +379,14 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, /* Special case for last column */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + - GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + - GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); neighsum += neighsum; neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + - GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); membersum = membersum * memberscale + neighsum * neighscale; *outptr = (JSAMPLE) ((membersum + 32768) >> 16); @@ -404,7 +404,7 @@ h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, METHODDEF(void) fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, - JSAMPARRAY input_data, JSAMPARRAY output_data) + JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow; JDIMENSION colctr; @@ -418,7 +418,7 @@ fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, * efficient. */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, - cinfo->image_width, output_cols); + cinfo->image_width, output_cols); /* Each of the eight neighbor pixels contributes a fraction SF to the * smoothed pixel, while the main pixel contributes (1-8*SF). In order @@ -437,10 +437,10 @@ fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, /* Special case for first column */ colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + - GETJSAMPLE(*inptr); + GETJSAMPLE(*inptr); membersum = GETJSAMPLE(*inptr++); nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + - GETJSAMPLE(*inptr); + GETJSAMPLE(*inptr); neighsum = colsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); @@ -450,7 +450,7 @@ fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, membersum = GETJSAMPLE(*inptr++); above_ptr++; below_ptr++; nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + - GETJSAMPLE(*inptr); + GETJSAMPLE(*inptr); neighsum = lastcolsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); @@ -485,7 +485,7 @@ jinit_downsampler (j_compress_ptr cinfo) downsample = (my_downsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_downsampler)); + SIZEOF(my_downsampler)); cinfo->downsample = (struct jpeg_downsampler *) downsample; downsample->pub.start_pass = start_pass_downsample; downsample->pub.downsample = sep_downsample; @@ -501,35 +501,35 @@ jinit_downsampler (j_compress_ptr cinfo) * are to be converted from max_h_samp_factor * max_v_samp_factor pixels. */ h_out_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / - cinfo->min_DCT_h_scaled_size; + cinfo->min_DCT_h_scaled_size; v_out_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / - cinfo->min_DCT_v_scaled_size; + cinfo->min_DCT_v_scaled_size; h_in_group = cinfo->max_h_samp_factor; v_in_group = cinfo->max_v_samp_factor; downsample->rowgroup_height[ci] = v_out_group; /* save for use later */ if (h_in_group == h_out_group && v_in_group == v_out_group) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { - downsample->methods[ci] = fullsize_smooth_downsample; - downsample->pub.need_context_rows = TRUE; + downsample->methods[ci] = fullsize_smooth_downsample; + downsample->pub.need_context_rows = TRUE; } else #endif - downsample->methods[ci] = fullsize_downsample; + downsample->methods[ci] = fullsize_downsample; } else if (h_in_group == h_out_group * 2 && - v_in_group == v_out_group) { + v_in_group == v_out_group) { smoothok = FALSE; downsample->methods[ci] = h2v1_downsample; } else if (h_in_group == h_out_group * 2 && - v_in_group == v_out_group * 2) { + v_in_group == v_out_group * 2) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { - downsample->methods[ci] = h2v2_smooth_downsample; - downsample->pub.need_context_rows = TRUE; + downsample->methods[ci] = h2v2_smooth_downsample; + downsample->pub.need_context_rows = TRUE; } else #endif - downsample->methods[ci] = h2v2_downsample; + downsample->methods[ci] = h2v2_downsample; } else if ((h_in_group % h_out_group) == 0 && - (v_in_group % v_out_group) == 0) { + (v_in_group % v_out_group) == 0) { smoothok = FALSE; downsample->methods[ci] = int_downsample; downsample->h_expand[ci] = (UINT8) (h_in_group / h_out_group); diff --git a/3rdparty/libjpeg/jctrans.c b/3rdparty/libjpeg/jctrans.c index 68a686b517..7cd077e4f6 100644 --- a/3rdparty/libjpeg/jctrans.c +++ b/3rdparty/libjpeg/jctrans.c @@ -2,7 +2,7 @@ * jctrans.c * * Copyright (C) 1995-1998, Thomas G. Lane. - * Modified 2000-2012 by Guido Vollbeding. + * Modified 2000-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -18,9 +18,9 @@ /* Forward declarations */ LOCAL(void) transencode_master_selection - JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); LOCAL(void) transencode_coef_controller - JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); + JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); /* @@ -62,7 +62,7 @@ jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) GLOBAL(void) jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, - j_compress_ptr dstinfo) + j_compress_ptr dstinfo) { JQUANT_TBL ** qtblptr; jpeg_component_info *incomp, *outcomp; @@ -97,10 +97,10 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; if (*qtblptr == NULL) - *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); + *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); MEMCOPY((*qtblptr)->quantval, - srcinfo->quant_tbl_ptrs[tblno]->quantval, - SIZEOF((*qtblptr)->quantval)); + srcinfo->quant_tbl_ptrs[tblno]->quantval, + SIZEOF((*qtblptr)->quantval)); (*qtblptr)->sent_table = FALSE; } } @@ -110,7 +110,7 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, dstinfo->num_components = srcinfo->num_components; if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, - MAX_COMPONENTS); + MAX_COMPONENTS); for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; ci < dstinfo->num_components; ci++, incomp++, outcomp++) { outcomp->component_id = incomp->component_id; @@ -123,14 +123,14 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, */ tblno = outcomp->quant_tbl_no; if (tblno < 0 || tblno >= NUM_QUANT_TBLS || - srcinfo->quant_tbl_ptrs[tblno] == NULL) + srcinfo->quant_tbl_ptrs[tblno] == NULL) ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); slot_quant = srcinfo->quant_tbl_ptrs[tblno]; c_quant = incomp->quant_table; if (c_quant != NULL) { for (coefi = 0; coefi < DCTSIZE2; coefi++) { - if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) - ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); + if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) + ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); } } /* Note: we do not copy the source's entropy table assignments; @@ -143,10 +143,10 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, * if the application chooses to copy JFIF 1.02 extension markers from * the source file, we need to copy the version to make sure we don't * emit a file that has 1.02 extensions but a claimed version of 1.01. - * We will *not*, however, copy version info from mislabeled "2.01" files. */ if (srcinfo->saw_JFIF_marker) { - if (srcinfo->JFIF_major_version == 1) { + if (srcinfo->JFIF_major_version == 1 || + srcinfo->JFIF_major_version == 2) { dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; } @@ -164,7 +164,7 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, LOCAL(void) transencode_master_selection (j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays) + jvirt_barray_ptr * coef_arrays) { /* Initialize master control (includes parameter checking/processing) */ jinit_c_master_control(cinfo, TRUE /* transcode only */); @@ -298,44 +298,44 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; - MCU_col_num++) { + MCU_col_num++) { /* Construct list of pointers to DCT blocks belonging to this MCU */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - start_col = MCU_col_num * compptr->MCU_width; - blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - if (coef->iMCU_row_num < last_iMCU_row || - yindex+yoffset < compptr->last_row_height) { - /* Fill in pointers to real blocks in this row */ - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < blockcnt; xindex++) - MCU_buffer[blkn++] = buffer_ptr++; - } else { - /* At bottom of image, need a whole row of dummy blocks */ - xindex = 0; - } - /* Fill in any dummy blocks needed in this row. - * Dummy blocks are filled in the same way as in jccoefct.c: - * all zeroes in the AC entries, DC entries equal to previous - * block's DC value. The init routine has already zeroed the - * AC entries, so we need only set the DC entries correctly. - */ - for (; xindex < compptr->MCU_width; xindex++) { - MCU_buffer[blkn] = coef->dummy_buffer[blkn]; - MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; - blkn++; - } - } + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (coef->iMCU_row_num < last_iMCU_row || + yindex+yoffset < compptr->last_row_height) { + /* Fill in pointers to real blocks in this row */ + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < blockcnt; xindex++) + MCU_buffer[blkn++] = buffer_ptr++; + } else { + /* At bottom of image, need a whole row of dummy blocks */ + xindex = 0; + } + /* Fill in any dummy blocks needed in this row. + * Dummy blocks are filled in the same way as in jccoefct.c: + * all zeroes in the AC entries, DC entries equal to previous + * block's DC value. The init routine has already zeroed the + * AC entries, so we need only set the DC entries correctly. + */ + for (; xindex < compptr->MCU_width; xindex++) { + MCU_buffer[blkn] = coef->dummy_buffer[blkn]; + MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; + blkn++; + } + } } /* Try to write the MCU. */ if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->mcu_ctr = MCU_col_num; - return FALSE; + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->mcu_ctr = MCU_col_num; + return FALSE; } } /* Completed an MCU row, but perhaps not an iMCU row */ @@ -358,7 +358,7 @@ compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) LOCAL(void) transencode_coef_controller (j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays) + jvirt_barray_ptr * coef_arrays) { my_coef_ptr coef; JBLOCKROW buffer; @@ -366,7 +366,7 @@ transencode_coef_controller (j_compress_ptr cinfo, coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_coef_controller)); + SIZEOF(my_coef_controller)); cinfo->coef = &coef->pub; coef->pub.start_pass = start_pass_coef; coef->pub.compress_data = compress_output; @@ -377,7 +377,7 @@ transencode_coef_controller (j_compress_ptr cinfo, /* Allocate and pre-zero space for dummy DCT blocks. */ buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); FMEMZERO((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { coef->dummy_buffer[i] = buffer + i; diff --git a/3rdparty/libjpeg/jdapimin.c b/3rdparty/libjpeg/jdapimin.c index e90e879bdd..a6e0dd9fb8 100644 --- a/3rdparty/libjpeg/jdapimin.c +++ b/3rdparty/libjpeg/jdapimin.c @@ -2,7 +2,7 @@ * jdapimin.c * * Copyright (C) 1994-1998, Thomas G. Lane. - * Modified 2009 by Guido Vollbeding. + * Modified 2009-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -37,8 +37,8 @@ jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) if (version != JPEG_LIB_VERSION) ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); if (structsize != SIZEOF(struct jpeg_decompress_struct)) - ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, - (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); + ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, + (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); /* For debugging purposes, we zero the whole master structure. * But the application has already set the err pointer, and may have set @@ -114,63 +114,66 @@ jpeg_abort_decompress (j_decompress_ptr cinfo) LOCAL(void) default_decompress_parms (j_decompress_ptr cinfo) { + int cid0, cid1, cid2; + /* Guess the input colorspace, and set output colorspace accordingly. */ - /* (Wish JPEG committee had provided a real way to specify this...) */ /* Note application may override our guesses. */ switch (cinfo->num_components) { case 1: cinfo->jpeg_color_space = JCS_GRAYSCALE; cinfo->out_color_space = JCS_GRAYSCALE; break; - + case 3: - if (cinfo->saw_JFIF_marker) { - cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ - } else if (cinfo->saw_Adobe_marker) { + cid0 = cinfo->comp_info[0].component_id; + cid1 = cinfo->comp_info[1].component_id; + cid2 = cinfo->comp_info[2].component_id; + + /* First try to guess from the component IDs */ + if (cid0 == 0x01 && cid1 == 0x02 && cid2 == 0x03) + cinfo->jpeg_color_space = JCS_YCbCr; + else if (cid0 == 0x01 && cid1 == 0x22 && cid2 == 0x23) + cinfo->jpeg_color_space = JCS_BG_YCC; + else if (cid0 == 0x52 && cid1 == 0x47 && cid2 == 0x42) + cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ + else if (cid0 == 0x72 && cid1 == 0x67 && cid2 == 0x62) + cinfo->jpeg_color_space = JCS_BG_RGB; /* ASCII 'r', 'g', 'b' */ + else if (cinfo->saw_JFIF_marker) + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + else if (cinfo->saw_Adobe_marker) { switch (cinfo->Adobe_transform) { case 0: - cinfo->jpeg_color_space = JCS_RGB; - break; + cinfo->jpeg_color_space = JCS_RGB; + break; case 1: - cinfo->jpeg_color_space = JCS_YCbCr; - break; + cinfo->jpeg_color_space = JCS_YCbCr; + break; default: - WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - break; + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ + break; } } else { - /* Saw no special markers, try to guess from the component IDs */ - int cid0 = cinfo->comp_info[0].component_id; - int cid1 = cinfo->comp_info[1].component_id; - int cid2 = cinfo->comp_info[2].component_id; - - if (cid0 == 1 && cid1 == 2 && cid2 == 3) - cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ - else if (cid0 == 82 && cid1 == 71 && cid2 == 66) - cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ - else { - TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); - cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ - } + TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); + cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ } /* Always guess RGB is proper output colorspace. */ cinfo->out_color_space = JCS_RGB; break; - + case 4: if (cinfo->saw_Adobe_marker) { switch (cinfo->Adobe_transform) { case 0: - cinfo->jpeg_color_space = JCS_CMYK; - break; + cinfo->jpeg_color_space = JCS_CMYK; + break; case 2: - cinfo->jpeg_color_space = JCS_YCCK; - break; + cinfo->jpeg_color_space = JCS_YCCK; + break; default: - WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); - cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ - break; + WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); + cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ + break; } } else { /* No special markers, assume straight CMYK. */ @@ -178,7 +181,7 @@ default_decompress_parms (j_decompress_ptr cinfo) } cinfo->out_color_space = JCS_CMYK; break; - + default: cinfo->jpeg_color_space = JCS_UNKNOWN; cinfo->out_color_space = JCS_UNKNOWN; diff --git a/3rdparty/libjpeg/jdapistd.c b/3rdparty/libjpeg/jdapistd.c index d4d9b0f672..7f3a78b25a 100644 --- a/3rdparty/libjpeg/jdapistd.c +++ b/3rdparty/libjpeg/jdapistd.c @@ -2,6 +2,7 @@ * jdapistd.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2002-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -52,24 +53,24 @@ jpeg_start_decompress (j_decompress_ptr cinfo) if (cinfo->inputctl->has_multiple_scans) { #ifdef D_MULTISCAN_FILES_SUPPORTED for (;;) { - int retcode; - /* Call progress monitor hook if present */ - if (cinfo->progress != NULL) - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); - /* Absorb some more input */ - retcode = (*cinfo->inputctl->consume_input) (cinfo); - if (retcode == JPEG_SUSPENDED) - return FALSE; - if (retcode == JPEG_REACHED_EOI) - break; - /* Advance progress counter if appropriate */ - if (cinfo->progress != NULL && - (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { - if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { - /* jdmaster underestimated number of scans; ratchet up one scan */ - cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; - } - } + int retcode; + /* Call progress monitor hook if present */ + if (cinfo->progress != NULL) + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + /* Absorb some more input */ + retcode = (*cinfo->inputctl->consume_input) (cinfo); + if (retcode == JPEG_SUSPENDED) + return FALSE; + if (retcode == JPEG_REACHED_EOI) + break; + /* Advance progress counter if appropriate */ + if (cinfo->progress != NULL && + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* jdmaster underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } + } } #else ERREXIT(cinfo, JERR_NOT_COMPILED); @@ -108,16 +109,16 @@ output_pass_setup (j_decompress_ptr cinfo) JDIMENSION last_scanline; /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { - cinfo->progress->pass_counter = (long) cinfo->output_scanline; - cinfo->progress->pass_limit = (long) cinfo->output_height; - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + cinfo->progress->pass_counter = (long) cinfo->output_scanline; + cinfo->progress->pass_limit = (long) cinfo->output_height; + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Process some data */ last_scanline = cinfo->output_scanline; (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, - &cinfo->output_scanline, (JDIMENSION) 0); + &cinfo->output_scanline, (JDIMENSION) 0); if (cinfo->output_scanline == last_scanline) - return FALSE; /* No progress made, must suspend */ + return FALSE; /* No progress made, must suspend */ } /* Finish up dummy pass, and set up for another one */ (*cinfo->master->finish_output_pass) (cinfo); @@ -150,7 +151,7 @@ output_pass_setup (j_decompress_ptr cinfo) GLOBAL(JDIMENSION) jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, - JDIMENSION max_lines) + JDIMENSION max_lines) { JDIMENSION row_ctr; @@ -183,7 +184,7 @@ jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, GLOBAL(JDIMENSION) jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, - JDIMENSION max_lines) + JDIMENSION max_lines) { JDIMENSION lines_per_iMCU_row; @@ -264,7 +265,7 @@ jpeg_finish_output (j_decompress_ptr cinfo) } /* Read markers looking for SOS or EOI */ while (cinfo->input_scan_number <= cinfo->output_scan_number && - ! cinfo->inputctl->eoi_reached) { + ! cinfo->inputctl->eoi_reached) { if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) return FALSE; /* Suspend, come back later */ } diff --git a/3rdparty/libjpeg/jdarith.c b/3rdparty/libjpeg/jdarith.c index 2e0d51a90e..5533c07397 100644 --- a/3rdparty/libjpeg/jdarith.c +++ b/3rdparty/libjpeg/jdarith.c @@ -1,7 +1,7 @@ /* * jdarith.c * - * Developed 1997-2012 by Guido Vollbeding. + * Developed 1997-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -94,7 +94,7 @@ get_byte (j_decompress_ptr cinfo) * (instead of fixed) with the bit shift counter CT. * Thus, we also need only one (variable instead of * fixed size) shift for the LPS/MPS decision, and - * we can get away with any renormalization update + * we can do away with any renormalization update * of C (except for new data insertion, of course). * * I've also introduced a new scheme for accessing @@ -115,32 +115,32 @@ arith_decode (j_decompress_ptr cinfo, unsigned char *st) if (--e->ct < 0) { /* Need to fetch next data byte */ if (cinfo->unread_marker) - data = 0; /* stuff zero data */ + data = 0; /* stuff zero data */ else { - data = get_byte(cinfo); /* read next input byte */ - if (data == 0xFF) { /* zero stuff or marker code */ - do data = get_byte(cinfo); - while (data == 0xFF); /* swallow extra 0xFF bytes */ - if (data == 0) - data = 0xFF; /* discard stuffed zero byte */ - else { - /* Note: Different from the Huffman decoder, hitting - * a marker while processing the compressed data - * segment is legal in arithmetic coding. - * The convention is to supply zero data - * then until decoding is complete. - */ - cinfo->unread_marker = data; - data = 0; - } - } + data = get_byte(cinfo); /* read next input byte */ + if (data == 0xFF) { /* zero stuff or marker code */ + do data = get_byte(cinfo); + while (data == 0xFF); /* swallow extra 0xFF bytes */ + if (data == 0) + data = 0xFF; /* discard stuffed zero byte */ + else { + /* Note: Different from the Huffman decoder, hitting + * a marker while processing the compressed data + * segment is legal in arithmetic coding. + * The convention is to supply zero data + * then until decoding is complete. + */ + cinfo->unread_marker = data; + data = 0; + } + } } e->c = (e->c << 8) | data; /* insert data into C register */ if ((e->ct += 8) < 0) /* update bit shift counter */ - /* Need more initial bytes */ - if (++e->ct == 0) - /* Got 2 initial bytes -> re-init A and exit loop */ - e->a = 0x8000L; /* => e->a = 0x10000L after loop exit */ + /* Need more initial bytes */ + if (++e->ct == 0) + /* Got 2 initial bytes -> re-init A and exit loop */ + e->a = 0x8000L; /* => e->a = 0x10000L after loop exit */ } e->a <<= 1; } @@ -207,7 +207,7 @@ process_restart (j_decompress_ptr cinfo) entropy->dc_context[ci] = 0; } if ((! cinfo->progressive_mode && cinfo->lim_Se) || - (cinfo->progressive_mode && cinfo->Ss)) { + (cinfo->progressive_mode && cinfo->Ss)) { MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS); } } @@ -278,28 +278,28 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) st += 2; st += sign; /* Figure F.23: Decoding the magnitude category of v */ if ((m = arith_decode(cinfo, st)) != 0) { - st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ - while (arith_decode(cinfo, st)) { - if ((m <<= 1) == 0x8000) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* magnitude overflow */ - return TRUE; - } - st += 1; - } + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } } /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) - entropy->dc_context[ci] = 0; /* zero diff category */ + entropy->dc_context[ci] = 0; /* zero diff category */ else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) - entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ + entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ else - entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ + entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ v = m; /* Figure F.24: Decoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) - if (arith_decode(cinfo, st)) v |= m; + if (arith_decode(cinfo, st)) v |= m; v += 1; if (sign) v = -v; entropy->last_dc_val[ci] += v; } @@ -354,9 +354,9 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) if (arith_decode(cinfo, st + 1)) break; st += 3; if (k >= cinfo->Se) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* spectral overflow */ - return TRUE; + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; } } /* Figure F.21: Decoding nonzero value v */ @@ -366,17 +366,17 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) /* Figure F.23: Decoding the magnitude category of v */ if ((m = arith_decode(cinfo, st)) != 0) { if (arith_decode(cinfo, st)) { - m <<= 1; - st = entropy->ac_stats[tbl] + - (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); - while (arith_decode(cinfo, st)) { - if ((m <<= 1) == 0x8000) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* magnitude overflow */ - return TRUE; - } - st += 1; - } + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } } } v = m; @@ -395,6 +395,8 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) /* * MCU decoding for DC successive approximation refinement scan. + * Note: we assume such scans can be multi-component, + * although the spec is not very clear on the point. */ METHODDEF(boolean) @@ -473,26 +475,26 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) for (;;) { thiscoef = *block + natural_order[++k]; if (*thiscoef) { /* previously nonzero coef */ - if (arith_decode(cinfo, st + 2)) { - if (*thiscoef < 0) - *thiscoef += m1; - else - *thiscoef += p1; - } - break; + if (arith_decode(cinfo, st + 2)) { + if (*thiscoef < 0) + *thiscoef += m1; + else + *thiscoef += p1; + } + break; } if (arith_decode(cinfo, st + 1)) { /* newly nonzero coef */ - if (arith_decode(cinfo, entropy->fixed_bin)) - *thiscoef = m1; - else - *thiscoef = p1; - break; + if (arith_decode(cinfo, entropy->fixed_bin)) + *thiscoef = m1; + else + *thiscoef = p1; + break; } st += 3; if (k >= cinfo->Se) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* spectral overflow */ - return TRUE; + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; } } } while (k < cinfo->Se); @@ -551,28 +553,28 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) st += 2; st += sign; /* Figure F.23: Decoding the magnitude category of v */ if ((m = arith_decode(cinfo, st)) != 0) { - st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ - while (arith_decode(cinfo, st)) { - if ((m <<= 1) == 0x8000) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* magnitude overflow */ - return TRUE; - } - st += 1; - } + st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */ + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } } /* Section F.1.4.4.1.2: Establish dc_context conditioning category */ if (m < (int) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) - entropy->dc_context[ci] = 0; /* zero diff category */ + entropy->dc_context[ci] = 0; /* zero diff category */ else if (m > (int) ((1L << cinfo->arith_dc_U[tbl]) >> 1)) - entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ + entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */ else - entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ + entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */ v = m; /* Figure F.24: Decoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) - if (arith_decode(cinfo, st)) v |= m; + if (arith_decode(cinfo, st)) v |= m; v += 1; if (sign) v = -v; entropy->last_dc_val[ci] += v; } @@ -590,14 +592,14 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) st = entropy->ac_stats[tbl] + 3 * k; if (arith_decode(cinfo, st)) break; /* EOB flag */ for (;;) { - k++; - if (arith_decode(cinfo, st + 1)) break; - st += 3; - if (k >= cinfo->lim_Se) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* spectral overflow */ - return TRUE; - } + k++; + if (arith_decode(cinfo, st + 1)) break; + st += 3; + if (k >= cinfo->lim_Se) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* spectral overflow */ + return TRUE; + } } /* Figure F.21: Decoding nonzero value v */ /* Figure F.22: Decoding the sign of v */ @@ -605,25 +607,25 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) st += 2; /* Figure F.23: Decoding the magnitude category of v */ if ((m = arith_decode(cinfo, st)) != 0) { - if (arith_decode(cinfo, st)) { - m <<= 1; - st = entropy->ac_stats[tbl] + - (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); - while (arith_decode(cinfo, st)) { - if ((m <<= 1) == 0x8000) { - WARNMS(cinfo, JWRN_ARITH_BAD_CODE); - entropy->ct = -1; /* magnitude overflow */ - return TRUE; - } - st += 1; - } - } + if (arith_decode(cinfo, st)) { + m <<= 1; + st = entropy->ac_stats[tbl] + + (k <= cinfo->arith_ac_K[tbl] ? 189 : 217); + while (arith_decode(cinfo, st)) { + if ((m <<= 1) == 0x8000) { + WARNMS(cinfo, JWRN_ARITH_BAD_CODE); + entropy->ct = -1; /* magnitude overflow */ + return TRUE; + } + st += 1; + } + } } v = m; /* Figure F.24: Decoding the magnitude bit pattern of v */ st += 14; while (m >>= 1) - if (arith_decode(cinfo, st)) v |= m; + if (arith_decode(cinfo, st)) v |= m; v += 1; if (sign) v = -v; (*block)[natural_order[k]] = (JCOEF) v; } while (k < cinfo->lim_Se); @@ -648,24 +650,24 @@ start_pass (j_decompress_ptr cinfo) /* Validate progressive scan parameters */ if (cinfo->Ss == 0) { if (cinfo->Se != 0) - goto bad; + goto bad; } else { /* need not check Ss/Se < 0 since they came from unsigned bytes */ if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) - goto bad; + goto bad; /* AC scans may have only one component */ if (cinfo->comps_in_scan != 1) - goto bad; + goto bad; } if (cinfo->Ah != 0) { /* Successive approximation refinement scan: must have Al = Ah-1. */ if (cinfo->Ah-1 != cinfo->Al) - goto bad; + goto bad; } if (cinfo->Al > 13) { /* need not check for < 0 */ bad: ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); } /* Update progression status, and verify that scan order is legal. * Note that inter-scan inconsistencies are treated as warnings @@ -675,32 +677,32 @@ start_pass (j_decompress_ptr cinfo) int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { - int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; - if (cinfo->Ah != expected) - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); - coef_bit_ptr[coefi] = cinfo->Al; + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; } } /* Select MCU decoding routine */ if (cinfo->Ah == 0) { if (cinfo->Ss == 0) - entropy->pub.decode_mcu = decode_mcu_DC_first; + entropy->pub.decode_mcu = decode_mcu_DC_first; else - entropy->pub.decode_mcu = decode_mcu_AC_first; + entropy->pub.decode_mcu = decode_mcu_AC_first; } else { if (cinfo->Ss == 0) - entropy->pub.decode_mcu = decode_mcu_DC_refine; + entropy->pub.decode_mcu = decode_mcu_DC_refine; else - entropy->pub.decode_mcu = decode_mcu_AC_refine; + entropy->pub.decode_mcu = decode_mcu_AC_refine; } } else { /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. * This ought to be an error condition, but we make it a warning. */ if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || - (cinfo->Se < DCTSIZE2 && cinfo->Se != cinfo->lim_Se)) + (cinfo->Se < DCTSIZE2 && cinfo->Se != cinfo->lim_Se)) WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); /* Select MCU decoding routine */ entropy->pub.decode_mcu = decode_mcu; @@ -712,23 +714,23 @@ start_pass (j_decompress_ptr cinfo) if (! cinfo->progressive_mode || (cinfo->Ss == 0 && cinfo->Ah == 0)) { tbl = compptr->dc_tbl_no; if (tbl < 0 || tbl >= NUM_ARITH_TBLS) - ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); if (entropy->dc_stats[tbl] == NULL) - entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); + entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS); MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS); /* Initialize DC predictions to 0 */ entropy->last_dc_val[ci] = 0; entropy->dc_context[ci] = 0; } if ((! cinfo->progressive_mode && cinfo->lim_Se) || - (cinfo->progressive_mode && cinfo->Ss)) { + (cinfo->progressive_mode && cinfo->Ss)) { tbl = compptr->ac_tbl_no; if (tbl < 0 || tbl >= NUM_ARITH_TBLS) - ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); + ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl); if (entropy->ac_stats[tbl] == NULL) - entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); + entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small) + ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS); MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS); } } @@ -743,6 +745,17 @@ start_pass (j_decompress_ptr cinfo) } +/* + * Finish up at the end of an arithmetic-compressed scan. + */ + +METHODDEF(void) +finish_pass (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + /* * Module initialization routine for arithmetic entropy decoding. */ @@ -755,9 +768,10 @@ jinit_arith_decoder (j_decompress_ptr cinfo) entropy = (arith_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(arith_entropy_decoder)); + SIZEOF(arith_entropy_decoder)); cinfo->entropy = &entropy->pub; entropy->pub.start_pass = start_pass; + entropy->pub.finish_pass = finish_pass; /* Mark tables unallocated */ for (i = 0; i < NUM_ARITH_TBLS; i++) { @@ -773,10 +787,10 @@ jinit_arith_decoder (j_decompress_ptr cinfo) int *coef_bit_ptr, ci; cinfo->coef_bits = (int (*)[DCTSIZE2]) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components*DCTSIZE2*SIZEOF(int)); + cinfo->num_components*DCTSIZE2*SIZEOF(int)); coef_bit_ptr = & cinfo->coef_bits[0][0]; - for (ci = 0; ci < cinfo->num_components; ci++) + for (ci = 0; ci < cinfo->num_components; ci++) for (i = 0; i < DCTSIZE2; i++) - *coef_bit_ptr++ = -1; + *coef_bit_ptr++ = -1; } } diff --git a/3rdparty/libjpeg/jdatadst.c b/3rdparty/libjpeg/jdatadst.c index 4997f478c2..5c8681c9e4 100644 --- a/3rdparty/libjpeg/jdatadst.c +++ b/3rdparty/libjpeg/jdatadst.c @@ -68,7 +68,7 @@ init_destination (j_compress_ptr cinfo) /* Allocate the output buffer --- it will be released when done with image */ dest->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; @@ -206,7 +206,7 @@ jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) if (cinfo->dest == NULL) { /* first time for this JPEG object? */ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_destination_mgr)); + SIZEOF(my_destination_mgr)); } dest = (my_dest_ptr) cinfo->dest; @@ -233,7 +233,7 @@ jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) GLOBAL(void) jpeg_mem_dest (j_compress_ptr cinfo, - unsigned char ** outbuffer, unsigned long * outsize) + unsigned char ** outbuffer, unsigned long * outsize) { my_mem_dest_ptr dest; @@ -246,7 +246,7 @@ jpeg_mem_dest (j_compress_ptr cinfo, if (cinfo->dest == NULL) { /* first time for this JPEG object? */ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_mem_destination_mgr)); + SIZEOF(my_mem_destination_mgr)); } dest = (my_mem_dest_ptr) cinfo->dest; diff --git a/3rdparty/libjpeg/jdatasrc.c b/3rdparty/libjpeg/jdatasrc.c index 5e417cc1e9..2a27cfed80 100644 --- a/3rdparty/libjpeg/jdatasrc.c +++ b/3rdparty/libjpeg/jdatasrc.c @@ -2,7 +2,7 @@ * jdatasrc.c * * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2009-2011 by Guido Vollbeding. + * Modified 2009-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -221,11 +221,11 @@ jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_source_mgr)); + SIZEOF(my_source_mgr)); src = (my_src_ptr) cinfo->src; src->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - INPUT_BUF_SIZE * SIZEOF(JOCTET)); + INPUT_BUF_SIZE * SIZEOF(JOCTET)); } src = (my_src_ptr) cinfo->src; @@ -247,7 +247,7 @@ jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) GLOBAL(void) jpeg_mem_src (j_decompress_ptr cinfo, - unsigned char * inbuffer, unsigned long insize) + const unsigned char * inbuffer, unsigned long insize) { struct jpeg_source_mgr * src; @@ -261,7 +261,7 @@ jpeg_mem_src (j_decompress_ptr cinfo, if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(struct jpeg_source_mgr)); + SIZEOF(struct jpeg_source_mgr)); } src = cinfo->src; @@ -271,5 +271,5 @@ jpeg_mem_src (j_decompress_ptr cinfo, src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->term_source = term_source; src->bytes_in_buffer = (size_t) insize; - src->next_input_byte = (JOCTET *) inbuffer; + src->next_input_byte = (const JOCTET *) inbuffer; } diff --git a/3rdparty/libjpeg/jdcoefct.c b/3rdparty/libjpeg/jdcoefct.c index 93066a27f6..ed02fc378f 100644 --- a/3rdparty/libjpeg/jdcoefct.c +++ b/3rdparty/libjpeg/jdcoefct.c @@ -64,15 +64,15 @@ typedef my_coef_controller * my_coef_ptr; /* Forward declarations */ METHODDEF(int) decompress_onepass - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); #ifdef D_MULTISCAN_FILES_SUPPORTED METHODDEF(int) decompress_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); #endif #ifdef BLOCK_SMOOTHING_SUPPORTED LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo)); METHODDEF(int) decompress_smooth_data - JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); + JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); #endif @@ -161,16 +161,16 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; - MCU_col_num++) { + MCU_col_num++) { /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ if (cinfo->lim_Se) /* can bypass in DC only case */ - FMEMZERO((void FAR *) coef->MCU_buffer[0], - (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); + FMEMZERO((void FAR *) coef->MCU_buffer[0], + (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->MCU_ctr = MCU_col_num; - return JPEG_SUSPENDED; + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; } /* Determine where data should go in output_buf and do the IDCT thing. * We skip dummy blocks at the right and bottom edges (but blkn gets @@ -179,32 +179,32 @@ decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Don't bother to IDCT an uninteresting component. */ - if (! compptr->component_needed) { - blkn += compptr->MCU_blocks; - continue; - } - inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; - useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width - : compptr->last_col_width; - output_ptr = output_buf[compptr->component_index] + - yoffset * compptr->DCT_v_scaled_size; - start_col = MCU_col_num * compptr->MCU_sample_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - if (cinfo->input_iMCU_row < last_iMCU_row || - yoffset+yindex < compptr->last_row_height) { - output_col = start_col; - for (xindex = 0; xindex < useful_width; xindex++) { - (*inverse_DCT) (cinfo, compptr, - (JCOEFPTR) coef->MCU_buffer[blkn+xindex], - output_ptr, output_col); - output_col += compptr->DCT_h_scaled_size; - } - } - blkn += compptr->MCU_width; - output_ptr += compptr->DCT_v_scaled_size; - } + compptr = cinfo->cur_comp_info[ci]; + /* Don't bother to IDCT an uninteresting component. */ + if (! compptr->component_needed) { + blkn += compptr->MCU_blocks; + continue; + } + inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; + useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width + : compptr->last_col_width; + output_ptr = output_buf[compptr->component_index] + + yoffset * compptr->DCT_v_scaled_size; + start_col = MCU_col_num * compptr->MCU_sample_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + if (cinfo->input_iMCU_row < last_iMCU_row || + yoffset+yindex < compptr->last_row_height) { + output_col = start_col; + for (xindex = 0; xindex < useful_width; xindex++) { + (*inverse_DCT) (cinfo, compptr, + (JCOEFPTR) coef->MCU_buffer[blkn+xindex], + output_ptr, output_col); + output_col += compptr->DCT_h_scaled_size; + } + } + blkn += compptr->MCU_width; + output_ptr += compptr->DCT_v_scaled_size; + } } } /* Completed an MCU row, but perhaps not an iMCU row */ @@ -270,25 +270,25 @@ consume_data (j_decompress_ptr cinfo) for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; - MCU_col_num++) { + MCU_col_num++) { /* Construct list of pointers to DCT blocks belonging to this MCU */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - start_col = MCU_col_num * compptr->MCU_width; - for (yindex = 0; yindex < compptr->MCU_height; yindex++) { - buffer_ptr = buffer[ci][yindex+yoffset] + start_col; - for (xindex = 0; xindex < compptr->MCU_width; xindex++) { - coef->MCU_buffer[blkn++] = buffer_ptr++; - } - } + compptr = cinfo->cur_comp_info[ci]; + start_col = MCU_col_num * compptr->MCU_width; + for (yindex = 0; yindex < compptr->MCU_height; yindex++) { + buffer_ptr = buffer[ci][yindex+yoffset] + start_col; + for (xindex = 0; xindex < compptr->MCU_width; xindex++) { + coef->MCU_buffer[blkn++] = buffer_ptr++; + } + } } /* Try to fetch the MCU. */ if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { - /* Suspension forced; update state counters and exit */ - coef->MCU_vert_offset = yoffset; - coef->MCU_ctr = MCU_col_num; - return JPEG_SUSPENDED; + /* Suspension forced; update state counters and exit */ + coef->MCU_vert_offset = yoffset; + coef->MCU_ctr = MCU_col_num; + return JPEG_SUSPENDED; } } /* Completed an MCU row, but perhaps not an iMCU row */ @@ -329,8 +329,8 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) /* Force some input to be done if we are getting ahead of the input. */ while (cinfo->input_scan_number < cinfo->output_scan_number || - (cinfo->input_scan_number == cinfo->output_scan_number && - cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { + (cinfo->input_scan_number == cinfo->output_scan_number && + cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) { if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) return JPEG_SUSPENDED; } @@ -361,10 +361,10 @@ decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) buffer_ptr = buffer[block_row]; output_col = 0; for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) { - (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, - output_ptr, output_col); - buffer_ptr++; - output_col += compptr->DCT_h_scaled_size; + (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr, + output_ptr, output_col); + buffer_ptr++; + output_col += compptr->DCT_h_scaled_size; } output_ptr += compptr->DCT_v_scaled_size; } @@ -421,8 +421,8 @@ smoothing_ok (j_decompress_ptr cinfo) if (coef->coef_bits_latch == NULL) coef->coef_bits_latch = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * - (SAVED_COEFS * SIZEOF(int))); + cinfo->num_components * + (SAVED_COEFS * SIZEOF(int))); coef_bits_latch = coef->coef_bits_latch; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; @@ -432,11 +432,11 @@ smoothing_ok (j_decompress_ptr cinfo) return FALSE; /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */ if (qtable->quantval[0] == 0 || - qtable->quantval[Q01_POS] == 0 || - qtable->quantval[Q10_POS] == 0 || - qtable->quantval[Q20_POS] == 0 || - qtable->quantval[Q11_POS] == 0 || - qtable->quantval[Q02_POS] == 0) + qtable->quantval[Q01_POS] == 0 || + qtable->quantval[Q10_POS] == 0 || + qtable->quantval[Q20_POS] == 0 || + qtable->quantval[Q11_POS] == 0 || + qtable->quantval[Q02_POS] == 0) return FALSE; /* DC values must be at least partly known for all components. */ coef_bits = cinfo->coef_bits[ci]; @@ -446,7 +446,7 @@ smoothing_ok (j_decompress_ptr cinfo) for (coefi = 1; coefi <= 5; coefi++) { coef_bits_latch[coefi] = coef_bits[coefi]; if (coef_bits[coefi] != 0) - smoothing_useful = TRUE; + smoothing_useful = TRUE; } coef_bits_latch += SAVED_COEFS; } @@ -482,7 +482,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) /* Force some input to be done if we are getting ahead of the input. */ while (cinfo->input_scan_number <= cinfo->output_scan_number && - ! cinfo->inputctl->eoi_reached) { + ! cinfo->inputctl->eoi_reached) { if (cinfo->input_scan_number == cinfo->output_scan_number) { /* If input is working on current scan, we ordinarily want it to * have completed the current row. But if input scan is DC, @@ -491,7 +491,7 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) */ JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0; if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta) - break; + break; } if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED) return JPEG_SUSPENDED; @@ -519,15 +519,15 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) if (cinfo->output_iMCU_row > 0) { access_rows += compptr->v_samp_factor; /* prior iMCU row too */ buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, - (JDIMENSION) access_rows, FALSE); + ((j_common_ptr) cinfo, coef->whole_image[ci], + (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor, + (JDIMENSION) access_rows, FALSE); buffer += compptr->v_samp_factor; /* point to current iMCU row */ first_row = FALSE; } else { buffer = (*cinfo->mem->access_virt_barray) - ((j_common_ptr) cinfo, coef->whole_image[ci], - (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); + ((j_common_ptr) cinfo, coef->whole_image[ci], + (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE); first_row = TRUE; } /* Fetch component-dependent info */ @@ -545,13 +545,13 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) for (block_row = 0; block_row < block_rows; block_row++) { buffer_ptr = buffer[block_row]; if (first_row && block_row == 0) - prev_block_row = buffer_ptr; + prev_block_row = buffer_ptr; else - prev_block_row = buffer[block_row-1]; + prev_block_row = buffer[block_row-1]; if (last_row && block_row == block_rows-1) - next_block_row = buffer_ptr; + next_block_row = buffer_ptr; else - next_block_row = buffer[block_row+1]; + next_block_row = buffer[block_row+1]; /* We fetch the surrounding DC values using a sliding-register approach. * Initialize all nine here so as to do the right thing on narrow pics. */ @@ -561,102 +561,102 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) output_col = 0; last_block_column = compptr->width_in_blocks - 1; for (block_num = 0; block_num <= last_block_column; block_num++) { - /* Fetch current DCT block into workspace so we can modify it. */ - jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); - /* Update DC values */ - if (block_num < last_block_column) { - DC3 = (int) prev_block_row[1][0]; - DC6 = (int) buffer_ptr[1][0]; - DC9 = (int) next_block_row[1][0]; - } - /* Compute coefficient estimates per K.8. - * An estimate is applied only if coefficient is still zero, - * and is not known to be fully accurate. - */ - /* AC01 */ - if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { - num = 36 * Q00 * (DC4 - DC6); - if (num >= 0) { - pred = (int) (((Q01<<7) + num) / (Q01<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q10<<7) + num) / (Q10<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q20<<7) + num) / (Q20<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q11<<7) + num) / (Q11<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q02<<7) + num) / (Q02<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<DCT_h_scaled_size; + /* Fetch current DCT block into workspace so we can modify it. */ + jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1); + /* Update DC values */ + if (block_num < last_block_column) { + DC3 = (int) prev_block_row[1][0]; + DC6 = (int) buffer_ptr[1][0]; + DC9 = (int) next_block_row[1][0]; + } + /* Compute coefficient estimates per K.8. + * An estimate is applied only if coefficient is still zero, + * and is not known to be fully accurate. + */ + /* AC01 */ + if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) { + num = 36 * Q00 * (DC4 - DC6); + if (num >= 0) { + pred = (int) (((Q01<<7) + num) / (Q01<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q10<<7) + num) / (Q10<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q20<<7) + num) / (Q20<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q11<<7) + num) / (Q11<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q02<<7) + num) / (Q02<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<DCT_h_scaled_size; } output_ptr += compptr->DCT_v_scaled_size; } @@ -681,7 +681,7 @@ jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_coef_controller)); + SIZEOF(my_coef_controller)); cinfo->coef = (struct jpeg_d_coef_controller *) coef; coef->pub.start_input_pass = start_input_pass; coef->pub.start_output_pass = start_output_pass; @@ -699,20 +699,20 @@ jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) jpeg_component_info *compptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { + ci++, compptr++) { access_rows = compptr->v_samp_factor; #ifdef BLOCK_SMOOTHING_SUPPORTED /* If block smoothing could be used, need a bigger window */ if (cinfo->progressive_mode) - access_rows *= 3; + access_rows *= 3; #endif coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, - (JDIMENSION) jround_up((long) compptr->width_in_blocks, - (long) compptr->h_samp_factor), - (JDIMENSION) jround_up((long) compptr->height_in_blocks, - (long) compptr->v_samp_factor), - (JDIMENSION) access_rows); + ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, + (JDIMENSION) jround_up((long) compptr->width_in_blocks, + (long) compptr->h_samp_factor), + (JDIMENSION) jround_up((long) compptr->height_in_blocks, + (long) compptr->v_samp_factor), + (JDIMENSION) access_rows); } coef->pub.consume_data = consume_data; coef->pub.decompress_data = decompress_data; @@ -727,13 +727,13 @@ jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); + D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } if (cinfo->lim_Se == 0) /* DC only case: want to bypass later */ FMEMZERO((void FAR *) buffer, - (size_t) (D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK))); + (size_t) (D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK))); coef->pub.consume_data = dummy_consume_data; coef->pub.decompress_data = decompress_onepass; coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ diff --git a/3rdparty/libjpeg/jdcolor.c b/3rdparty/libjpeg/jdcolor.c index 83c17a2c19..29c30fae51 100644 --- a/3rdparty/libjpeg/jdcolor.c +++ b/3rdparty/libjpeg/jdcolor.c @@ -2,7 +2,7 @@ * jdcolor.c * * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2011-2012 by Guido Vollbeding. + * Modified 2011-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -19,7 +19,7 @@ typedef struct { struct jpeg_color_deconverter pub; /* public fields */ - /* Private state for YCC->RGB conversion */ + /* Private state for YCbCr->RGB and BG_YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ int * Cb_b_tab; /* => table for Cb to B conversion */ INT32 * Cr_g_tab; /* => table for Cr to G conversion */ @@ -32,22 +32,44 @@ typedef struct { typedef my_color_deconverter * my_cconvert_ptr; -/**************** YCbCr -> RGB conversion: most common case **************/ -/**************** RGB -> Y conversion: less common case **************/ +/*************** YCbCr -> RGB conversion: most common case **************/ +/*************** BG_YCC -> RGB conversion: less common case **************/ +/*************** RGB -> Y conversion: less common case **************/ /* - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore + * YCbCr is defined per Recommendation ITU-R BT.601-7 (03/2011), + * previously known as Recommendation CCIR 601-1, except that Cb and Cr + * are normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * sRGB (standard RGB color space) is defined per IEC 61966-2-1:1999. + * sYCC (standard luma-chroma-chroma color space with extended gamut) + * is defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex F. + * bg-sRGB and bg-sYCC (big gamut standard color spaces) + * are defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex G. + * Note that the derived conversion coefficients given in some of these + * documents are imprecise. The general conversion equations are * - * R = Y + 1.40200 * Cr - * G = Y - 0.34414 * Cb - 0.71414 * Cr - * B = Y + 1.77200 * Cb + * R = Y + K * (1 - Kr) * Cr + * G = Y - K * (Kb * (1 - Kb) * Cb + Kr * (1 - Kr) * Cr) / (1 - Kr - Kb) + * B = Y + K * (1 - Kb) * Cb * - * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * Y = Kr * R + (1 - Kr - Kb) * G + Kb * B + * + * With Kr = 0.299 and Kb = 0.114 (derived according to SMPTE RP 177-1993 + * from the 1953 FCC NTSC primaries and CIE Illuminant C), K = 2 for sYCC, + * the conversion equations to be implemented are therefore + * + * R = Y + 1.402 * Cr + * G = Y - 0.344136286 * Cb - 0.714136286 * Cr + * B = Y + 1.772 * Cb + * + * Y = 0.299 * R + 0.587 * G + 0.114 * B * * where Cb and Cr represent the incoming values less CENTERJSAMPLE. - * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + * For bg-sYCC, with K = 4, the equations are + * + * R = Y + 2.804 * Cr + * G = Y - 0.688272572 * Cb - 1.428272572 * Cr + * B = Y + 3.544 * Cb * * To avoid floating-point arithmetic, we represent the fractional constants * as integers scaled up by 2^16 (about 4 digits precision); we have to divide @@ -58,9 +80,9 @@ typedef my_color_deconverter * my_cconvert_ptr; * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times Cb and Cr for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); - * for 12-bit samples it is still acceptable. It's not very reasonable for - * 16-bit samples, but if you want lossless storage you shouldn't be changing - * colorspace anyway. + * for 9-bit to 12-bit samples it is still acceptable. It's not very + * reasonable for 16-bit samples, but if you want lossless storage you + * shouldn't be changing colorspace anyway. * The Cr=>R and Cb=>B values can be rounded to integers in advance; the * values for the G calculation are left scaled up, since we must add them * together before rounding. @@ -84,11 +106,12 @@ typedef my_color_deconverter * my_cconvert_ptr; /* - * Initialize tables for YCC->RGB colorspace conversion. + * Initialize tables for YCbCr->RGB and BG_YCC->RGB colorspace conversion. */ LOCAL(void) build_ycc_rgb_table (j_decompress_ptr cinfo) +/* Normal case, sYCC */ { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; int i; @@ -97,31 +120,71 @@ build_ycc_rgb_table (j_decompress_ptr cinfo) cconvert->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); + (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); + (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cr_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); + (MAXJSAMPLE+1) * SIZEOF(INT32)); cconvert->Cb_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); + (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.40200 * x */ + /* Cr=>R value is nearest int to 1.402 * x */ cconvert->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.77200 * x */ + RIGHT_SHIFT(FIX(1.402) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.772 * x */ cconvert->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.71414 * x */ - cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; - /* Cb=>G value is scaled-up -0.34414 * x */ + RIGHT_SHIFT(FIX(1.772) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.714136286 * x */ + cconvert->Cr_g_tab[i] = (- FIX(0.714136286)) * x; + /* Cb=>G value is scaled-up -0.344136286 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ - cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + cconvert->Cb_g_tab[i] = (- FIX(0.344136286)) * x + ONE_HALF; + } +} + + +LOCAL(void) +build_bg_ycc_rgb_table (j_decompress_ptr cinfo) +/* Wide gamut case, bg-sYCC */ +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + int i; + INT32 x; + SHIFT_TEMPS + + cconvert->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + cconvert->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + cconvert->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 2.804 * x */ + cconvert->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(2.804) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 3.544 * x */ + cconvert->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(3.544) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -1.428272572 * x */ + cconvert->Cr_g_tab[i] = (- FIX(1.428272572)) * x; + /* Cb=>G value is scaled-up -0.688272572 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + cconvert->Cb_g_tab[i] = (- FIX(0.688272572)) * x + ONE_HALF; } } @@ -139,8 +202,8 @@ build_ycc_rgb_table (j_decompress_ptr cinfo) METHODDEF(void) ycc_rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; @@ -166,19 +229,21 @@ ycc_rgb_convert (j_decompress_ptr cinfo, y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ - outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; + /* Range-limiting is essential due to noise introduced by DCT losses, + * for extended gamut (sYCC) and wide gamut (bg-sYCC) encodings. + */ + outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; outptr[RGB_GREEN] = range_limit[y + - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS))]; - outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS))]; + outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; outptr += RGB_PIXELSIZE; } } } -/**************** Cases other than YCbCr -> RGB **************/ +/**************** Cases other than YCC -> RGB ****************/ /* @@ -195,12 +260,12 @@ build_rgb_y_table (j_decompress_ptr cinfo) /* Allocate and fill in the conversion tables. */ cconvert->rgb_y_tab = rgb_y_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (TABLE_SIZE * SIZEOF(INT32))); + (TABLE_SIZE * SIZEOF(INT32))); for (i = 0; i <= MAXJSAMPLE; i++) { - rgb_y_tab[i+R_Y_OFF] = FIX(0.29900) * i; - rgb_y_tab[i+G_Y_OFF] = FIX(0.58700) * i; - rgb_y_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; + rgb_y_tab[i+R_Y_OFF] = FIX(0.299) * i; + rgb_y_tab[i+G_Y_OFF] = FIX(0.587) * i; + rgb_y_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF; } } @@ -211,8 +276,8 @@ build_rgb_y_table (j_decompress_ptr cinfo) METHODDEF(void) rgb_gray_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register INT32 * ctab = cconvert->rgb_y_tab; @@ -234,8 +299,8 @@ rgb_gray_convert (j_decompress_ptr cinfo, b = GETJSAMPLE(inptr2[col]); /* Y */ outptr[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); } } } @@ -244,12 +309,15 @@ rgb_gray_convert (j_decompress_ptr cinfo, /* * [R-G,G,B-G] to [R,G,B] conversion with modulo calculation * (inverse color transform). + * This can be seen as an adaption of the general YCbCr->RGB + * conversion equation with Kr = Kb = 0, while replacing the + * normalization by modulo calculation. */ METHODDEF(void) rgb1_rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) { register int r, g, b; register JSAMPROW outptr; @@ -286,8 +354,8 @@ rgb1_rgb_convert (j_decompress_ptr cinfo, METHODDEF(void) rgb1_gray_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register INT32 * ctab = cconvert->rgb_y_tab; @@ -314,8 +382,8 @@ rgb1_gray_convert (j_decompress_ptr cinfo, b = (b + g - CENTERJSAMPLE) & MAXJSAMPLE; /* Y */ outptr[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); } } } @@ -328,8 +396,8 @@ rgb1_gray_convert (j_decompress_ptr cinfo, METHODDEF(void) rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) { register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2; @@ -360,8 +428,8 @@ rgb_convert (j_decompress_ptr cinfo, METHODDEF(void) null_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) { int ci; register int nc = cinfo->num_components; @@ -375,8 +443,8 @@ null_convert (j_decompress_ptr cinfo, inptr = input_buf[ci][input_row]; outptr = output_buf[0] + ci; for (col = 0; col < num_cols; col++) { - *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ - outptr += nc; + *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ + outptr += nc; } } input_row++; @@ -387,17 +455,17 @@ null_convert (j_decompress_ptr cinfo, /* * Color conversion for grayscale: just copy the data. - * This also works for YCbCr -> grayscale conversion, in which + * This also works for YCC -> grayscale conversion, in which * we just copy the Y (luminance) component and ignore chrominance. */ METHODDEF(void) grayscale_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) { jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, - num_rows, cinfo->output_width); + num_rows, cinfo->output_width); } @@ -409,8 +477,8 @@ grayscale_convert (j_decompress_ptr cinfo, METHODDEF(void) gray_rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) { register JSAMPROW outptr; register JSAMPROW inptr; @@ -438,8 +506,8 @@ gray_rgb_convert (j_decompress_ptr cinfo, METHODDEF(void) ycck_cmyk_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; @@ -466,11 +534,13 @@ ycck_cmyk_convert (j_decompress_ptr cinfo, y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); - /* Range-limiting is essential due to noise introduced by DCT losses. */ + /* Range-limiting is essential due to noise introduced by DCT losses, + * and for extended gamut encodings (sYCC). + */ outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ - ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], - SCALEBITS)))]; + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], + SCALEBITS)))]; outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ /* K passes through unchanged */ outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ @@ -503,7 +573,7 @@ jinit_color_deconverter (j_decompress_ptr cinfo) cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_color_deconverter)); + SIZEOF(my_color_deconverter)); cinfo->cconvert = &cconvert->pub; cconvert->pub.start_pass = start_pass_dcolor; @@ -516,6 +586,8 @@ jinit_color_deconverter (j_decompress_ptr cinfo) case JCS_RGB: case JCS_YCbCr: + case JCS_BG_RGB: + case JCS_BG_YCC: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; @@ -532,8 +604,10 @@ jinit_color_deconverter (j_decompress_ptr cinfo) break; } - /* Support color transform only for RGB colorspace */ - if (cinfo->color_transform && cinfo->jpeg_color_space != JCS_RGB) + /* Support color transform only for RGB colorspaces */ + if (cinfo->color_transform && + cinfo->jpeg_color_space != JCS_RGB && + cinfo->jpeg_color_space != JCS_BG_RGB) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); /* Set out_color_components and conversion method based on requested space. @@ -544,47 +618,76 @@ jinit_color_deconverter (j_decompress_ptr cinfo) switch (cinfo->out_color_space) { case JCS_GRAYSCALE: cinfo->out_color_components = 1; - if (cinfo->jpeg_color_space == JCS_GRAYSCALE || - cinfo->jpeg_color_space == JCS_YCbCr) { + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + case JCS_YCbCr: + case JCS_BG_YCC: cconvert->pub.color_convert = grayscale_convert; /* For color->grayscale conversion, only the Y (0) component is needed */ for (ci = 1; ci < cinfo->num_components; ci++) - cinfo->comp_info[ci].component_needed = FALSE; - } else if (cinfo->jpeg_color_space == JCS_RGB) { + cinfo->comp_info[ci].component_needed = FALSE; + break; + case JCS_RGB: switch (cinfo->color_transform) { case JCT_NONE: - cconvert->pub.color_convert = rgb_gray_convert; - break; + cconvert->pub.color_convert = rgb_gray_convert; + break; case JCT_SUBTRACT_GREEN: - cconvert->pub.color_convert = rgb1_gray_convert; - break; + cconvert->pub.color_convert = rgb1_gray_convert; + break; default: - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } build_rgb_y_table(cinfo); - } else + break; + default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } break; case JCS_RGB: cinfo->out_color_components = RGB_PIXELSIZE; - if (cinfo->jpeg_color_space == JCS_YCbCr) { + switch (cinfo->jpeg_color_space) { + case JCS_GRAYSCALE: + cconvert->pub.color_convert = gray_rgb_convert; + break; + case JCS_YCbCr: cconvert->pub.color_convert = ycc_rgb_convert; build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { - cconvert->pub.color_convert = gray_rgb_convert; - } else if (cinfo->jpeg_color_space == JCS_RGB) { + break; + case JCS_BG_YCC: + cconvert->pub.color_convert = ycc_rgb_convert; + build_bg_ycc_rgb_table(cinfo); + break; + case JCS_RGB: switch (cinfo->color_transform) { case JCT_NONE: - cconvert->pub.color_convert = rgb_convert; - break; + cconvert->pub.color_convert = rgb_convert; + break; case JCT_SUBTRACT_GREEN: - cconvert->pub.color_convert = rgb1_rgb_convert; - break; + cconvert->pub.color_convert = rgb1_rgb_convert; + break; default: - ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); - break; + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } + break; + default: + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } + break; + + case JCS_BG_RGB: + cinfo->out_color_components = RGB_PIXELSIZE; + if (cinfo->jpeg_color_space == JCS_BG_RGB) { + switch (cinfo->color_transform) { + case JCT_NONE: + cconvert->pub.color_convert = rgb_convert; + break; + case JCT_SUBTRACT_GREEN: + cconvert->pub.color_convert = rgb1_rgb_convert; + break; + default: + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); } } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); @@ -592,13 +695,17 @@ jinit_color_deconverter (j_decompress_ptr cinfo) case JCS_CMYK: cinfo->out_color_components = 4; - if (cinfo->jpeg_color_space == JCS_YCCK) { + switch (cinfo->jpeg_color_space) { + case JCS_YCCK: cconvert->pub.color_convert = ycck_cmyk_convert; build_ycc_rgb_table(cinfo); - } else if (cinfo->jpeg_color_space == JCS_CMYK) { + break; + case JCS_CMYK: cconvert->pub.color_convert = null_convert; - } else + break; + default: ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } break; default: diff --git a/3rdparty/libjpeg/jdct.h b/3rdparty/libjpeg/jdct.h index 8240f4ea0a..5d0fe83fb2 100644 --- a/3rdparty/libjpeg/jdct.h +++ b/3rdparty/libjpeg/jdct.h @@ -2,13 +2,14 @@ * jdct.h * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2002-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This include file contains common declarations for the forward and * inverse DCT modules. These declarations are private to the DCT managers * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. - * The individual DCT algorithms are kept in separate files to ease + * The individual DCT algorithms are kept in separate files to ease * machine-dependent tuning (e.g., assembly coding). */ @@ -38,11 +39,11 @@ typedef INT32 DCTELEM; /* must have 32 bits */ #endif typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data, - JSAMPARRAY sample_data, - JDIMENSION start_col)); + JSAMPARRAY sample_data, + JDIMENSION start_col)); typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data, - JSAMPARRAY sample_data, - JDIMENSION start_col)); + JSAMPARRAY sample_data, + JDIMENSION start_col)); /* @@ -78,13 +79,16 @@ typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */ * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could * be quite far out of range if the input data is corrupt, so a bulletproof * range-limiting step is required. We use a mask-and-table-lookup method - * to do the combined operations quickly. See the comments with - * prepare_range_limit_table (in jdmaster.c) for more info. + * to do the combined operations quickly, assuming that MAXJSAMPLE+1 + * is a power of 2. See the comments with prepare_range_limit_table + * (in jdmaster.c) for more info. */ -#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) - #define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ +#define RANGE_CENTER (MAXJSAMPLE * 2 + 2) +#define RANGE_SUBSET (RANGE_CENTER - CENTERJSAMPLE) + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit - RANGE_SUBSET) /* Short forms of external names for systems with brain-damaged linkers. */ @@ -233,106 +237,106 @@ EXTERN(void) jpeg_fdct_1x2 EXTERN(void) jpeg_idct_islow JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_ifast JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_float JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_7x7 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_6x6 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_5x5 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_4x4 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_3x3 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_2x2 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_1x1 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_9x9 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_10x10 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_11x11 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_12x12 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_13x13 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_14x14 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_15x15 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_16x16 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_16x8 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_14x7 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_12x6 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_10x5 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_8x4 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_6x3 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_4x2 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_2x1 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_8x16 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_7x14 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_6x12 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_5x10 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_4x8 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_3x6 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_2x4 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN(void) jpeg_idct_1x2 JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); + JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); /* @@ -391,3 +395,23 @@ EXTERN(void) jpeg_idct_1x2 #ifndef MULTIPLY16V16 /* default definition */ #define MULTIPLY16V16(var1,var2) ((var1) * (var2)) #endif + +/* Like RIGHT_SHIFT, but applies to a DCTELEM. + * We assume that int right shift is unsigned if INT32 right shift is. + */ + +#ifdef RIGHT_SHIFT_IS_UNSIGNED +#define ISHIFT_TEMPS DCTELEM ishift_temp; +#if BITS_IN_JSAMPLE == 8 +#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ +#else +#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ +#endif +#define IRIGHT_SHIFT(x,shft) \ + ((ishift_temp = (x)) < 0 ? \ + (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ + (ishift_temp >> (shft))) +#else +#define ISHIFT_TEMPS +#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) +#endif diff --git a/3rdparty/libjpeg/jddctmgr.c b/3rdparty/libjpeg/jddctmgr.c index ce49314968..9ecfbb5107 100644 --- a/3rdparty/libjpeg/jddctmgr.c +++ b/3rdparty/libjpeg/jddctmgr.c @@ -2,7 +2,7 @@ * jddctmgr.c * * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2002-2010 by Guido Vollbeding. + * Modified 2002-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -230,30 +230,30 @@ start_pass (j_decompress_ptr cinfo) switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: - method_ptr = jpeg_idct_islow; - method = JDCT_ISLOW; - break; + method_ptr = jpeg_idct_islow; + method = JDCT_ISLOW; + break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: - method_ptr = jpeg_idct_ifast; - method = JDCT_IFAST; - break; + method_ptr = jpeg_idct_ifast; + method = JDCT_IFAST; + break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: - method_ptr = jpeg_idct_float; - method = JDCT_FLOAT; - break; + method_ptr = jpeg_idct_float; + method = JDCT_FLOAT; + break; #endif default: - ERREXIT(cinfo, JERR_NOT_COMPILED); - break; + ERREXIT(cinfo, JERR_NOT_COMPILED); + break; } break; default: ERREXIT2(cinfo, JERR_BAD_DCTSIZE, - compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); + compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size); break; } idct->pub.inverse_DCT[ci] = method_ptr; @@ -274,75 +274,75 @@ start_pass (j_decompress_ptr cinfo) #ifdef PROVIDE_ISLOW_TABLES case JDCT_ISLOW: { - /* For LL&M IDCT method, multipliers are equal to raw quantization - * coefficients, but are stored as ints to ensure access efficiency. - */ - ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; - for (i = 0; i < DCTSIZE2; i++) { - ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; - } + /* For LL&M IDCT method, multipliers are equal to raw quantization + * coefficients, but are stored as ints to ensure access efficiency. + */ + ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; + for (i = 0; i < DCTSIZE2; i++) { + ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; + } } break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: { - /* For AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * For integer operation, the multiplier table is to be scaled by - * IFAST_SCALE_BITS. - */ - IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; + /* For AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * For integer operation, the multiplier table is to be scaled by + * IFAST_SCALE_BITS. + */ + IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; #define CONST_BITS 14 - static const INT16 aanscales[DCTSIZE2] = { - /* precomputed values scaled up by 14 bits */ - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, - 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, - 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, - 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, - 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, - 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, - 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 - }; - SHIFT_TEMPS + static const INT16 aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + SHIFT_TEMPS - for (i = 0; i < DCTSIZE2; i++) { - ifmtbl[i] = (IFAST_MULT_TYPE) - DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], - (INT32) aanscales[i]), - CONST_BITS-IFAST_SCALE_BITS); - } + for (i = 0; i < DCTSIZE2; i++) { + ifmtbl[i] = (IFAST_MULT_TYPE) + DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], + (INT32) aanscales[i]), + CONST_BITS-IFAST_SCALE_BITS); + } } break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: { - /* For float AA&N IDCT method, multipliers are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 1/8. - */ - FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; - int row, col; - static const double aanscalefactor[DCTSIZE] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; + /* For float AA&N IDCT method, multipliers are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 1/8. + */ + FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; + int row, col; + static const double aanscalefactor[DCTSIZE] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; - i = 0; - for (row = 0; row < DCTSIZE; row++) { - for (col = 0; col < DCTSIZE; col++) { - fmtbl[i] = (FLOAT_MULT_TYPE) - ((double) qtbl->quantval[i] * - aanscalefactor[row] * aanscalefactor[col] * 0.125); - i++; - } - } + i = 0; + for (row = 0; row < DCTSIZE; row++) { + for (col = 0; col < DCTSIZE; col++) { + fmtbl[i] = (FLOAT_MULT_TYPE) + ((double) qtbl->quantval[i] * + aanscalefactor[row] * aanscalefactor[col] * 0.125); + i++; + } + } } break; #endif @@ -367,8 +367,8 @@ jinit_inverse_dct (j_decompress_ptr cinfo) idct = (my_idct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_idct_controller)); - cinfo->idct = (struct jpeg_inverse_dct *) idct; + SIZEOF(my_idct_controller)); + cinfo->idct = &idct->pub; idct->pub.start_pass = start_pass; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; @@ -376,7 +376,7 @@ jinit_inverse_dct (j_decompress_ptr cinfo) /* Allocate and pre-zero a multiplier table for each component */ compptr->dct_table = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(multiplier_table)); + SIZEOF(multiplier_table)); MEMZERO(compptr->dct_table, SIZEOF(multiplier_table)); /* Mark multiplier table not yet set up for any method */ idct->cur_method[ci] = -1; diff --git a/3rdparty/libjpeg/jdhuff.c b/3rdparty/libjpeg/jdhuff.c index e76c0d0abe..6920e207c8 100644 --- a/3rdparty/libjpeg/jdhuff.c +++ b/3rdparty/libjpeg/jdhuff.c @@ -2,7 +2,7 @@ * jdhuff.c * * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2006-2012 by Guido Vollbeding. + * Modified 2006-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -97,22 +97,22 @@ typedef struct { /* Bitreading working state within an MCU */ /* Macros to declare and load/save bitread local variables. */ #define BITREAD_STATE_VARS \ - register bit_buf_type get_buffer; \ - register int bits_left; \ - bitread_working_state br_state + register bit_buf_type get_buffer; \ + register int bits_left; \ + bitread_working_state br_state #define BITREAD_LOAD_STATE(cinfop,permstate) \ - br_state.cinfo = cinfop; \ - br_state.next_input_byte = cinfop->src->next_input_byte; \ - br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ - get_buffer = permstate.get_buffer; \ - bits_left = permstate.bits_left; + br_state.cinfo = cinfop; \ + br_state.next_input_byte = cinfop->src->next_input_byte; \ + br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \ + get_buffer = permstate.get_buffer; \ + bits_left = permstate.bits_left; #define BITREAD_SAVE_STATE(cinfop,permstate) \ - cinfop->src->next_input_byte = br_state.next_input_byte; \ - cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ - permstate.get_buffer = get_buffer; \ - permstate.bits_left = bits_left + cinfop->src->next_input_byte = br_state.next_input_byte; \ + cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \ + permstate.get_buffer = get_buffer; \ + permstate.bits_left = bits_left /* * These macros provide the in-line portion of bit fetching. @@ -133,19 +133,19 @@ typedef struct { /* Bitreading working state within an MCU */ */ #define CHECK_BIT_BUFFER(state,nbits,action) \ - { if (bits_left < (nbits)) { \ - if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ - { action; } \ - get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } + { if (bits_left < (nbits)) { \ + if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \ + { action; } \ + get_buffer = (state).get_buffer; bits_left = (state).bits_left; } } #define GET_BITS(nbits) \ - (((int) (get_buffer >> (bits_left -= (nbits)))) & BIT_MASK(nbits)) + (((int) (get_buffer >> (bits_left -= (nbits)))) & BIT_MASK(nbits)) #define PEEK_BITS(nbits) \ - (((int) (get_buffer >> (bits_left - (nbits)))) & BIT_MASK(nbits)) + (((int) (get_buffer >> (bits_left - (nbits)))) & BIT_MASK(nbits)) #define DROP_BITS(nbits) \ - (bits_left -= (nbits)) + (bits_left -= (nbits)) /* @@ -182,7 +182,7 @@ typedef struct { /* Bitreading working state within an MCU */ nb = HUFF_LOOKAHEAD+1; \ slowlabel: \ if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \ - { failaction; } \ + { failaction; } \ get_buffer = state.get_buffer; bits_left = state.bits_left; \ } \ } @@ -210,11 +210,11 @@ typedef struct { #else #if MAX_COMPS_IN_SCAN == 4 #define ASSIGN_STATE(dest,src) \ - ((dest).EOBRUN = (src).EOBRUN, \ - (dest).last_dc_val[0] = (src).last_dc_val[0], \ - (dest).last_dc_val[1] = (src).last_dc_val[1], \ - (dest).last_dc_val[2] = (src).last_dc_val[2], \ - (dest).last_dc_val[3] = (src).last_dc_val[3]) + ((dest).EOBRUN = (src).EOBRUN, \ + (dest).last_dc_val[0] = (src).last_dc_val[0], \ + (dest).last_dc_val[1] = (src).last_dc_val[1], \ + (dest).last_dc_val[2] = (src).last_dc_val[2], \ + (dest).last_dc_val[3] = (src).last_dc_val[3]) #endif #endif @@ -321,7 +321,7 @@ static const int jpeg_zigzag_order2[2][2] = { LOCAL(void) jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, - d_derived_tbl ** pdtbl) + d_derived_tbl ** pdtbl) { JHUFF_TBL *htbl; d_derived_tbl *dtbl; @@ -347,10 +347,10 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, if (*pdtbl == NULL) *pdtbl = (d_derived_tbl *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(d_derived_tbl)); + SIZEOF(d_derived_tbl)); dtbl = *pdtbl; dtbl->pub = htbl; /* fill in back link */ - + /* Figure C.1: make table of Huffman code length for each symbol */ p = 0; @@ -363,10 +363,10 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, } huffsize[p] = 0; numsymbols = p; - + /* Figure C.2: generate the codes themselves */ /* We also validate that the counts represent a legal Huffman code tree. */ - + code = 0; si = huffsize[0]; p = 0; @@ -417,9 +417,9 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, /* Generate left-justified code followed by all possible bit sequences */ lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { - dtbl->look_nbits[lookbits] = l; - dtbl->look_sym[lookbits] = htbl->huffval[p]; - lookbits++; + dtbl->look_nbits[lookbits] = l; + dtbl->look_sym[lookbits] = htbl->huffval[p]; + lookbits++; } } } @@ -434,7 +434,7 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, for (i = 0; i < numsymbols; i++) { int sym = htbl->huffval[i]; if (sym < 0 || sym > 15) - ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); } } } @@ -463,8 +463,8 @@ jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, LOCAL(boolean) jpeg_fill_bit_buffer (bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - int nbits) + register bit_buf_type get_buffer, register int bits_left, + int nbits) /* Load up the bit buffer to a depth of at least nbits */ { /* Copy heavily used state fields into locals (hopefully registers) */ @@ -482,48 +482,48 @@ jpeg_fill_bit_buffer (bitread_working_state * state, /* Attempt to read a byte */ if (bytes_in_buffer == 0) { - if (! (*cinfo->src->fill_input_buffer) (cinfo)) - return FALSE; - next_input_byte = cinfo->src->next_input_byte; - bytes_in_buffer = cinfo->src->bytes_in_buffer; + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; } bytes_in_buffer--; c = GETJOCTET(*next_input_byte++); /* If it's 0xFF, check and discard stuffed zero byte */ if (c == 0xFF) { - /* Loop here to discard any padding FF's on terminating marker, - * so that we can save a valid unread_marker value. NOTE: we will - * accept multiple FF's followed by a 0 as meaning a single FF data - * byte. This data pattern is not valid according to the standard. - */ - do { - if (bytes_in_buffer == 0) { - if (! (*cinfo->src->fill_input_buffer) (cinfo)) - return FALSE; - next_input_byte = cinfo->src->next_input_byte; - bytes_in_buffer = cinfo->src->bytes_in_buffer; - } - bytes_in_buffer--; - c = GETJOCTET(*next_input_byte++); - } while (c == 0xFF); + /* Loop here to discard any padding FF's on terminating marker, + * so that we can save a valid unread_marker value. NOTE: we will + * accept multiple FF's followed by a 0 as meaning a single FF data + * byte. This data pattern is not valid according to the standard. + */ + do { + if (bytes_in_buffer == 0) { + if (! (*cinfo->src->fill_input_buffer) (cinfo)) + return FALSE; + next_input_byte = cinfo->src->next_input_byte; + bytes_in_buffer = cinfo->src->bytes_in_buffer; + } + bytes_in_buffer--; + c = GETJOCTET(*next_input_byte++); + } while (c == 0xFF); - if (c == 0) { - /* Found FF/00, which represents an FF data byte */ - c = 0xFF; - } else { - /* Oops, it's actually a marker indicating end of compressed data. - * Save the marker code for later use. - * Fine point: it might appear that we should save the marker into - * bitread working state, not straight into permanent state. But - * once we have hit a marker, we cannot need to suspend within the - * current MCU, because we will read no more bytes from the data - * source. So it is OK to update permanent state right away. - */ - cinfo->unread_marker = c; - /* See if we need to insert some fake zero bits. */ - goto no_more_bytes; - } + if (c == 0) { + /* Found FF/00, which represents an FF data byte */ + c = 0xFF; + } else { + /* Oops, it's actually a marker indicating end of compressed data. + * Save the marker code for later use. + * Fine point: it might appear that we should save the marker into + * bitread working state, not straight into permanent state. But + * once we have hit a marker, we cannot need to suspend within the + * current MCU, because we will read no more bytes from the data + * source. So it is OK to update permanent state right away. + */ + cinfo->unread_marker = c; + /* See if we need to insert some fake zero bits. */ + goto no_more_bytes; + } } /* OK, load c into get_buffer */ @@ -543,8 +543,8 @@ jpeg_fill_bit_buffer (bitread_working_state * state, * appears per data segment. */ if (! ((huff_entropy_ptr) cinfo->entropy)->insufficient_data) { - WARNMS(cinfo, JWRN_HIT_MARKER); - ((huff_entropy_ptr) cinfo->entropy)->insufficient_data = TRUE; + WARNMS(cinfo, JWRN_HIT_MARKER); + ((huff_entropy_ptr) cinfo->entropy)->insufficient_data = TRUE; } /* Fill the buffer with zero bits */ get_buffer <<= MIN_GET_BITS - bits_left; @@ -590,8 +590,8 @@ static const int bmask[16] = /* bmask[n] is mask for n rightmost bits */ LOCAL(int) jpeg_huff_decode (bitread_working_state * state, - register bit_buf_type get_buffer, register int bits_left, - d_derived_tbl * htbl, int min_bits) + register bit_buf_type get_buffer, register int bits_left, + d_derived_tbl * htbl, int min_bits) { register int l = min_bits; register INT32 code; @@ -627,6 +627,22 @@ jpeg_huff_decode (bitread_working_state * state, } +/* + * Finish up at the end of a Huffman-compressed scan. + */ + +METHODDEF(void) +finish_pass_huff (j_decompress_ptr cinfo) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + + /* Throw away any unused bits remaining in bit buffer; */ + /* include any full bytes in next_marker's count of discarded bytes */ + cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; + entropy->bitstate.bits_left = 0; +} + + /* * Check for a restart marker & resynchronize decoder. * Returns FALSE if must suspend. @@ -638,10 +654,7 @@ process_restart (j_decompress_ptr cinfo) huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci; - /* Throw away any unused bits remaining in bit buffer; */ - /* include any full bytes in next_marker's count of discarded bytes */ - cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8; - entropy->bitstate.bits_left = 0; + finish_pass_huff(cinfo); /* Advance past the RSTn marker */ if (! (*cinfo->marker->read_restart_marker) (cinfo)) @@ -671,7 +684,7 @@ process_restart (j_decompress_ptr cinfo) /* * Huffman MCU decoding. * Each of these routines decodes and returns one MCU's worth of - * Huffman-compressed coefficients. + * Huffman-compressed coefficients. * The coefficients are reordered from zigzag order into natural array order, * but are not dequantized. * @@ -693,7 +706,7 @@ process_restart (j_decompress_ptr cinfo) METHODDEF(boolean) decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ +{ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int Al = cinfo->Al; register int s, r; @@ -708,7 +721,7 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) - return FALSE; + return FALSE; } /* If we've run out of data, just leave the MCU set to zeroes. @@ -733,9 +746,9 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) /* Section F.2.2.1: decode the DC coefficient difference */ HUFF_DECODE(s, br_state, tbl, return FALSE, label1); if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); } /* Convert DC difference to actual value, update last_dc_val */ @@ -764,7 +777,7 @@ decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) METHODDEF(boolean) decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ +{ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; register int s, k, r; unsigned int EOBRUN; @@ -778,7 +791,7 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) - return FALSE; + return FALSE; } /* If we've run out of data, just leave the MCU set to zeroes. @@ -805,29 +818,29 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) tbl = entropy->ac_derived_tbl; for (k = cinfo->Ss; k <= Se; k++) { - HUFF_DECODE(s, br_state, tbl, return FALSE, label2); - r = s >> 4; - s &= 15; - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Scale and output coefficient in natural (dezigzagged) order */ - (*block)[natural_order[k]] = (JCOEF) (s << Al); - } else { - if (r != 15) { /* EOBr, run length is 2^r + appended bits */ - if (r) { /* EOBr, r > 0 */ - EOBRUN = 1 << r; - CHECK_BIT_BUFFER(br_state, r, return FALSE); - r = GET_BITS(r); - EOBRUN += r; - EOBRUN--; /* this band is processed at this moment */ - } - break; /* force end-of-band */ - } - k += 15; /* ZRL: skip 15 zeroes in band */ - } + HUFF_DECODE(s, br_state, tbl, return FALSE, label2); + r = s >> 4; + s &= 15; + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Scale and output coefficient in natural (dezigzagged) order */ + (*block)[natural_order[k]] = (JCOEF) (s << Al); + } else { + if (r != 15) { /* EOBr, run length is 2^r + appended bits */ + if (r) { /* EOBr, r > 0 */ + EOBRUN = 1 << r; + CHECK_BIT_BUFFER(br_state, r, return FALSE); + r = GET_BITS(r); + EOBRUN += r; + EOBRUN--; /* this band is processed at this moment */ + } + break; /* force end-of-band */ + } + k += 15; /* ZRL: skip 15 zeroes in band */ + } } BITREAD_SAVE_STATE(cinfo,entropy->bitstate); @@ -846,24 +859,22 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) /* * MCU decoding for DC successive approximation refinement scan. - * Note: we assume such scans can be multi-component, although the spec - * is not very clear on the point. + * Note: we assume such scans can be multi-component, + * although the spec is not very clear on the point. */ METHODDEF(boolean) decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ +{ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - int blkn; - JBLOCKROW block; + int p1, blkn; BITREAD_STATE_VARS; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) - return FALSE; + return FALSE; } /* Not worth the cycles to check insufficient_data here, @@ -873,15 +884,15 @@ decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) /* Load up working state */ BITREAD_LOAD_STATE(cinfo,entropy->bitstate); + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - block = MCU_data[blkn]; - /* Encoded data is simply the next bit of the two's-complement DC value */ CHECK_BIT_BUFFER(br_state, 1, return FALSE); if (GET_BITS(1)) - (*block)[0] |= p1; + MCU_data[blkn][0][0] |= p1; /* Note: since we use |=, repeating the assignment later is safe */ } @@ -901,7 +912,7 @@ decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) METHODDEF(boolean) decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ +{ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; register int s, k, r; unsigned int EOBRUN; @@ -918,7 +929,7 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) - return FALSE; + return FALSE; } /* If we've run out of data, don't modify the MCU. @@ -951,59 +962,59 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) if (EOBRUN == 0) { do { - HUFF_DECODE(s, br_state, tbl, goto undoit, label3); - r = s >> 4; - s &= 15; - if (s) { - if (s != 1) /* size of new coef should always be 1 */ - WARNMS(cinfo, JWRN_HUFF_BAD_CODE); - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) - s = p1; /* newly nonzero coef is positive */ - else - s = m1; /* newly nonzero coef is negative */ - } else { - if (r != 15) { - EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ - if (r) { - CHECK_BIT_BUFFER(br_state, r, goto undoit); - r = GET_BITS(r); - EOBRUN += r; - } - break; /* rest of block is handled by EOB logic */ - } - /* note s = 0 for processing ZRL */ - } - /* Advance over already-nonzero coefs and r still-zero coefs, - * appending correction bits to the nonzeroes. A correction bit is 1 - * if the absolute value of the coefficient must be increased. - */ - do { - thiscoef = *block + natural_order[k]; - if (*thiscoef) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } else { - if (--r < 0) - break; /* reached target zero coefficient */ - } - k++; - } while (k <= Se); - if (s) { - int pos = natural_order[k]; - /* Output newly nonzero coefficient */ - (*block)[pos] = (JCOEF) s; - /* Remember its position in case we have to suspend */ - newnz_pos[num_newnz++] = pos; - } - k++; + HUFF_DECODE(s, br_state, tbl, goto undoit, label3); + r = s >> 4; + s &= 15; + if (s) { + if (s != 1) /* size of new coef should always be 1 */ + WARNMS(cinfo, JWRN_HUFF_BAD_CODE); + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) + s = p1; /* newly nonzero coef is positive */ + else + s = m1; /* newly nonzero coef is negative */ + } else { + if (r != 15) { + EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */ + if (r) { + CHECK_BIT_BUFFER(br_state, r, goto undoit); + r = GET_BITS(r); + EOBRUN += r; + } + break; /* rest of block is handled by EOB logic */ + } + /* note s = 0 for processing ZRL */ + } + /* Advance over already-nonzero coefs and r still-zero coefs, + * appending correction bits to the nonzeroes. A correction bit is 1 + * if the absolute value of the coefficient must be increased. + */ + do { + thiscoef = *block + natural_order[k]; + if (*thiscoef) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already set it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } else { + if (--r < 0) + break; /* reached target zero coefficient */ + } + k++; + } while (k <= Se); + if (s) { + int pos = natural_order[k]; + /* Output newly nonzero coefficient */ + (*block)[pos] = (JCOEF) s; + /* Remember its position in case we have to suspend */ + newnz_pos[num_newnz++] = pos; + } + k++; } while (k <= Se); } @@ -1014,19 +1025,19 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) * if the absolute value of the coefficient must be increased. */ do { - thiscoef = *block + natural_order[k]; - if (*thiscoef) { - CHECK_BIT_BUFFER(br_state, 1, goto undoit); - if (GET_BITS(1)) { - if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ - if (*thiscoef >= 0) - *thiscoef += p1; - else - *thiscoef += m1; - } - } - } - k++; + thiscoef = *block + natural_order[k]; + if (*thiscoef) { + CHECK_BIT_BUFFER(br_state, 1, goto undoit); + if (GET_BITS(1)) { + if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */ + if (*thiscoef >= 0) + *thiscoef += p1; + else + *thiscoef += m1; + } + } + } + k++; } while (k <= Se); /* Count one block completed in EOB run */ EOBRUN--; @@ -1069,7 +1080,7 @@ decode_mcu_sub (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) - return FALSE; + return FALSE; } /* If we've run out of data, just leave the MCU set to zeroes. @@ -1102,66 +1113,66 @@ decode_mcu_sub (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) k = 1; coef_limit = entropy->coef_limit[blkn]; if (coef_limit) { - /* Convert DC difference to actual value, update last_dc_val */ - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - ci = cinfo->MCU_membership[blkn]; - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Output the DC coefficient */ - (*block)[0] = (JCOEF) s; + /* Convert DC difference to actual value, update last_dc_val */ + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient */ + (*block)[0] = (JCOEF) s; - /* Section F.2.2.2: decode the AC coefficients */ - /* Since zeroes are skipped, output area must be cleared beforehand */ - for (; k < coef_limit; k++) { - HUFF_DECODE(s, br_state, htbl, return FALSE, label2); + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (; k < coef_limit; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label2); - r = s >> 4; - s &= 15; + r = s >> 4; + s &= 15; - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Output coefficient in natural (dezigzagged) order. - * Note: the extra entries in natural_order[] will save us - * if k > Se, which could happen if the data is corrupted. - */ - (*block)[natural_order[k]] = (JCOEF) s; - } else { - if (r != 15) - goto EndOfBlock; - k += 15; - } - } + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in natural_order[] will save us + * if k > Se, which could happen if the data is corrupted. + */ + (*block)[natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + goto EndOfBlock; + k += 15; + } + } } else { - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } } /* Section F.2.2.2: decode the AC coefficients */ /* In this path we just discard the values */ for (; k <= Se; k++) { - HUFF_DECODE(s, br_state, htbl, return FALSE, label3); + HUFF_DECODE(s, br_state, htbl, return FALSE, label3); - r = s >> 4; - s &= 15; + r = s >> 4; + s &= 15; - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } else { - if (r != 15) - break; - k += 15; - } + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } } EndOfBlock: ; @@ -1196,7 +1207,7 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) - return FALSE; + return FALSE; } /* If we've run out of data, just leave the MCU set to zeroes. @@ -1226,66 +1237,66 @@ decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) k = 1; coef_limit = entropy->coef_limit[blkn]; if (coef_limit) { - /* Convert DC difference to actual value, update last_dc_val */ - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - } - ci = cinfo->MCU_membership[blkn]; - s += state.last_dc_val[ci]; - state.last_dc_val[ci] = s; - /* Output the DC coefficient */ - (*block)[0] = (JCOEF) s; + /* Convert DC difference to actual value, update last_dc_val */ + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + } + ci = cinfo->MCU_membership[blkn]; + s += state.last_dc_val[ci]; + state.last_dc_val[ci] = s; + /* Output the DC coefficient */ + (*block)[0] = (JCOEF) s; - /* Section F.2.2.2: decode the AC coefficients */ - /* Since zeroes are skipped, output area must be cleared beforehand */ - for (; k < coef_limit; k++) { - HUFF_DECODE(s, br_state, htbl, return FALSE, label2); + /* Section F.2.2.2: decode the AC coefficients */ + /* Since zeroes are skipped, output area must be cleared beforehand */ + for (; k < coef_limit; k++) { + HUFF_DECODE(s, br_state, htbl, return FALSE, label2); - r = s >> 4; - s &= 15; + r = s >> 4; + s &= 15; - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - r = GET_BITS(s); - s = HUFF_EXTEND(r, s); - /* Output coefficient in natural (dezigzagged) order. - * Note: the extra entries in jpeg_natural_order[] will save us - * if k >= DCTSIZE2, which could happen if the data is corrupted. - */ - (*block)[jpeg_natural_order[k]] = (JCOEF) s; - } else { - if (r != 15) - goto EndOfBlock; - k += 15; - } - } + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + r = GET_BITS(s); + s = HUFF_EXTEND(r, s); + /* Output coefficient in natural (dezigzagged) order. + * Note: the extra entries in jpeg_natural_order[] will save us + * if k >= DCTSIZE2, which could happen if the data is corrupted. + */ + (*block)[jpeg_natural_order[k]] = (JCOEF) s; + } else { + if (r != 15) + goto EndOfBlock; + k += 15; + } + } } else { - if (s) { - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } + if (s) { + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } } /* Section F.2.2.2: decode the AC coefficients */ /* In this path we just discard the values */ for (; k < DCTSIZE2; k++) { - HUFF_DECODE(s, br_state, htbl, return FALSE, label3); + HUFF_DECODE(s, br_state, htbl, return FALSE, label3); - r = s >> 4; - s &= 15; + r = s >> 4; + s &= 15; - if (s) { - k += r; - CHECK_BIT_BUFFER(br_state, s, return FALSE); - DROP_BITS(s); - } else { - if (r != 15) - break; - k += 15; - } + if (s) { + k += r; + CHECK_BIT_BUFFER(br_state, s, return FALSE); + DROP_BITS(s); + } else { + if (r != 15) + break; + k += 15; + } } EndOfBlock: ; @@ -1318,19 +1329,19 @@ start_pass_huff_decoder (j_decompress_ptr cinfo) /* Validate progressive scan parameters */ if (cinfo->Ss == 0) { if (cinfo->Se != 0) - goto bad; + goto bad; } else { /* need not check Ss/Se < 0 since they came from unsigned bytes */ if (cinfo->Se < cinfo->Ss || cinfo->Se > cinfo->lim_Se) - goto bad; + goto bad; /* AC scans may have only one component */ if (cinfo->comps_in_scan != 1) - goto bad; + goto bad; } if (cinfo->Ah != 0) { /* Successive approximation refinement scan: must have Al = Ah-1. */ if (cinfo->Ah-1 != cinfo->Al) - goto bad; + goto bad; } if (cinfo->Al > 13) { /* need not check for < 0 */ /* Arguably the maximum Al value should be less than 13 for 8-bit precision, @@ -1341,7 +1352,7 @@ start_pass_huff_decoder (j_decompress_ptr cinfo) */ bad: ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); } /* Update progression status, and verify that scan order is legal. * Note that inter-scan inconsistencies are treated as warnings @@ -1351,26 +1362,26 @@ start_pass_huff_decoder (j_decompress_ptr cinfo) int coefi, cindex = cinfo->cur_comp_info[ci]->component_index; int *coef_bit_ptr = & cinfo->coef_bits[cindex][0]; if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */ - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0); for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) { - int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; - if (cinfo->Ah != expected) - WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); - coef_bit_ptr[coefi] = cinfo->Al; + int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi]; + if (cinfo->Ah != expected) + WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr[coefi] = cinfo->Al; } } /* Select MCU decoding routine */ if (cinfo->Ah == 0) { if (cinfo->Ss == 0) - entropy->pub.decode_mcu = decode_mcu_DC_first; + entropy->pub.decode_mcu = decode_mcu_DC_first; else - entropy->pub.decode_mcu = decode_mcu_AC_first; + entropy->pub.decode_mcu = decode_mcu_AC_first; } else { if (cinfo->Ss == 0) - entropy->pub.decode_mcu = decode_mcu_DC_refine; + entropy->pub.decode_mcu = decode_mcu_DC_refine; else - entropy->pub.decode_mcu = decode_mcu_AC_refine; + entropy->pub.decode_mcu = decode_mcu_AC_refine; } for (ci = 0; ci < cinfo->comps_in_scan; ci++) { @@ -1379,17 +1390,17 @@ start_pass_huff_decoder (j_decompress_ptr cinfo) * We may build same derived table more than once, but it's not expensive. */ if (cinfo->Ss == 0) { - if (cinfo->Ah == 0) { /* DC refinement needs no table */ - tbl = compptr->dc_tbl_no; - jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, - & entropy->derived_tbls[tbl]); - } + if (cinfo->Ah == 0) { /* DC refinement needs no table */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } } else { - tbl = compptr->ac_tbl_no; - jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, - & entropy->derived_tbls[tbl]); - /* remember the single active table */ - entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; } /* Initialize DC predictions to 0 */ entropy->saved.last_dc_val[ci] = 0; @@ -1403,8 +1414,8 @@ start_pass_huff_decoder (j_decompress_ptr cinfo) * there are some baseline files out there with all zeroes in these bytes. */ if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || - ((cinfo->is_baseline || cinfo->Se < DCTSIZE2) && - cinfo->Se != cinfo->lim_Se)) + ((cinfo->is_baseline || cinfo->Se < DCTSIZE2) && + cinfo->Se != cinfo->lim_Se)) WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); /* Select MCU decoding routine */ @@ -1425,11 +1436,11 @@ start_pass_huff_decoder (j_decompress_ptr cinfo) /* We may do this more than once for a table, but it's not expensive */ tbl = compptr->dc_tbl_no; jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, - & entropy->dc_derived_tbls[tbl]); + & entropy->dc_derived_tbls[tbl]); if (cinfo->lim_Se) { /* AC needs no table when not present */ - tbl = compptr->ac_tbl_no; - jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, - & entropy->ac_derived_tbls[tbl]); + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->ac_derived_tbls[tbl]); } /* Initialize DC predictions to 0 */ entropy->saved.last_dc_val[ci] = 0; @@ -1444,50 +1455,50 @@ start_pass_huff_decoder (j_decompress_ptr cinfo) entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no]; /* Decide whether we really care about the coefficient values */ if (compptr->component_needed) { - ci = compptr->DCT_v_scaled_size; - i = compptr->DCT_h_scaled_size; - switch (cinfo->lim_Se) { - case (1*1-1): - entropy->coef_limit[blkn] = 1; - break; - case (2*2-1): - if (ci <= 0 || ci > 2) ci = 2; - if (i <= 0 || i > 2) i = 2; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order2[ci - 1][i - 1]; - break; - case (3*3-1): - if (ci <= 0 || ci > 3) ci = 3; - if (i <= 0 || i > 3) i = 3; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order3[ci - 1][i - 1]; - break; - case (4*4-1): - if (ci <= 0 || ci > 4) ci = 4; - if (i <= 0 || i > 4) i = 4; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order4[ci - 1][i - 1]; - break; - case (5*5-1): - if (ci <= 0 || ci > 5) ci = 5; - if (i <= 0 || i > 5) i = 5; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order5[ci - 1][i - 1]; - break; - case (6*6-1): - if (ci <= 0 || ci > 6) ci = 6; - if (i <= 0 || i > 6) i = 6; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order6[ci - 1][i - 1]; - break; - case (7*7-1): - if (ci <= 0 || ci > 7) ci = 7; - if (i <= 0 || i > 7) i = 7; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order7[ci - 1][i - 1]; - break; - default: - if (ci <= 0 || ci > 8) ci = 8; - if (i <= 0 || i > 8) i = 8; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order[ci - 1][i - 1]; - break; - } + ci = compptr->DCT_v_scaled_size; + i = compptr->DCT_h_scaled_size; + switch (cinfo->lim_Se) { + case (1*1-1): + entropy->coef_limit[blkn] = 1; + break; + case (2*2-1): + if (ci <= 0 || ci > 2) ci = 2; + if (i <= 0 || i > 2) i = 2; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order2[ci - 1][i - 1]; + break; + case (3*3-1): + if (ci <= 0 || ci > 3) ci = 3; + if (i <= 0 || i > 3) i = 3; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order3[ci - 1][i - 1]; + break; + case (4*4-1): + if (ci <= 0 || ci > 4) ci = 4; + if (i <= 0 || i > 4) i = 4; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order4[ci - 1][i - 1]; + break; + case (5*5-1): + if (ci <= 0 || ci > 5) ci = 5; + if (i <= 0 || i > 5) i = 5; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order5[ci - 1][i - 1]; + break; + case (6*6-1): + if (ci <= 0 || ci > 6) ci = 6; + if (i <= 0 || i > 6) i = 6; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order6[ci - 1][i - 1]; + break; + case (7*7-1): + if (ci <= 0 || ci > 7) ci = 7; + if (i <= 0 || i > 7) i = 7; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order7[ci - 1][i - 1]; + break; + default: + if (ci <= 0 || ci > 8) ci = 8; + if (i <= 0 || i > 8) i = 8; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order[ci - 1][i - 1]; + break; + } } else { - entropy->coef_limit[blkn] = 0; + entropy->coef_limit[blkn] = 0; } } } @@ -1514,20 +1525,21 @@ jinit_huff_decoder (j_decompress_ptr cinfo) entropy = (huff_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(huff_entropy_decoder)); + SIZEOF(huff_entropy_decoder)); cinfo->entropy = &entropy->pub; entropy->pub.start_pass = start_pass_huff_decoder; + entropy->pub.finish_pass = finish_pass_huff; if (cinfo->progressive_mode) { /* Create progression status table */ int *coef_bit_ptr, ci; cinfo->coef_bits = (int (*)[DCTSIZE2]) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components*DCTSIZE2*SIZEOF(int)); + cinfo->num_components*DCTSIZE2*SIZEOF(int)); coef_bit_ptr = & cinfo->coef_bits[0][0]; for (ci = 0; ci < cinfo->num_components; ci++) for (i = 0; i < DCTSIZE2; i++) - *coef_bit_ptr++ = -1; + *coef_bit_ptr++ = -1; /* Mark derived tables unallocated */ for (i = 0; i < NUM_HUFF_TBLS; i++) { diff --git a/3rdparty/libjpeg/jdinput.c b/3rdparty/libjpeg/jdinput.c index 137b5c694b..0199553e89 100644 --- a/3rdparty/libjpeg/jdinput.c +++ b/3rdparty/libjpeg/jdinput.c @@ -2,7 +2,7 @@ * jdinput.c * * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2002-2009 by Guido Vollbeding. + * Modified 2002-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -196,7 +196,7 @@ jpeg_core_output_dimensions (j_decompress_ptr cinfo) /* Hardwire it to "no scaling" */ cinfo->output_width = cinfo->image_width; cinfo->output_height = cinfo->image_height; - /* jdinput.c has already initialized DCT_scaled_size, + /* initial_setup has already initialized DCT_scaled_size, * and has computed unscaled downsampled_width and downsampled_height. */ @@ -216,14 +216,14 @@ initial_setup (j_decompress_ptr cinfo) (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - /* For now, precision must match compiled-in value... */ - if (cinfo->data_precision != BITS_IN_JSAMPLE) + /* Only 8 to 12 bits data precision are supported for DCT based JPEG */ + if (cinfo->data_precision < 8 || cinfo->data_precision > 12) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, - MAX_COMPONENTS); + MAX_COMPONENTS); /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; @@ -231,12 +231,12 @@ initial_setup (j_decompress_ptr cinfo) for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || - compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) + compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo, JERR_BAD_SAMPLING); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, - compptr->h_samp_factor); + compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, - compptr->v_samp_factor); + compptr->v_samp_factor); } /* Derive block_size, natural_order, and lim_Se */ @@ -329,7 +329,7 @@ initial_setup (j_decompress_ptr cinfo) break; default: ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); break; } @@ -350,10 +350,10 @@ initial_setup (j_decompress_ptr cinfo) /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* downsampled_width and downsampled_height will also be overridden by * jdmaster.c if we are doing full decompression. The transcoder library * doesn't use these values, but the calling application might. @@ -361,10 +361,10 @@ initial_setup (j_decompress_ptr cinfo) /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, - (long) cinfo->max_h_samp_factor); + (long) cinfo->max_h_samp_factor); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) cinfo->max_v_samp_factor); + (long) cinfo->max_v_samp_factor); /* Mark component needed, until color conversion says otherwise */ compptr->component_needed = TRUE; /* Mark no quantization table yet saved for component */ @@ -374,7 +374,7 @@ initial_setup (j_decompress_ptr cinfo) /* Compute number of fully interleaved MCU rows. */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); /* Decide whether file contains multiple scans */ if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) @@ -391,16 +391,16 @@ per_scan_setup (j_decompress_ptr cinfo) { int ci, mcublks, tmp; jpeg_component_info *compptr; - + if (cinfo->comps_in_scan == 1) { - + /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; - + /* Overall image size in MCUs */ cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; - + /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; @@ -413,28 +413,28 @@ per_scan_setup (j_decompress_ptr cinfo) tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (tmp == 0) tmp = compptr->v_samp_factor; compptr->last_row_height = tmp; - + /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; - + } else { - + /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, - MAX_COMPS_IN_SCAN); - + MAX_COMPS_IN_SCAN); + /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, - (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); - + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + cinfo->blocks_in_MCU = 0; - + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Sampling factors give # of blocks of component in each MCU */ @@ -452,12 +452,12 @@ per_scan_setup (j_decompress_ptr cinfo) /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) - ERREXIT(cinfo, JERR_BAD_MCU_SIZE); + ERREXIT(cinfo, JERR_BAD_MCU_SIZE); while (mcublks-- > 0) { - cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; + cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } - + } } @@ -498,12 +498,12 @@ latch_quant_tables (j_decompress_ptr cinfo) /* Make sure specified quantization table is present */ qtblno = compptr->quant_tbl_no; if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || - cinfo->quant_tbl_ptrs[qtblno] == NULL) + cinfo->quant_tbl_ptrs[qtblno] == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); /* OK, save away the quantization table */ qtbl = (JQUANT_TBL *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(JQUANT_TBL)); + SIZEOF(JQUANT_TBL)); MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); compptr->quant_table = qtbl; } @@ -537,6 +537,7 @@ start_input_pass (j_decompress_ptr cinfo) METHODDEF(void) finish_input_pass (j_decompress_ptr cinfo) { + (*cinfo->entropy->finish_pass) (cinfo); cinfo->inputctl->consume_input = consume_markers; } @@ -570,36 +571,36 @@ consume_markers (j_decompress_ptr cinfo) switch (val) { case JPEG_REACHED_SOS: /* Found SOS */ if (inputctl->inheaders) { /* 1st SOS */ - if (inputctl->inheaders == 1) - initial_setup(cinfo); - if (cinfo->comps_in_scan == 0) { /* pseudo SOS marker */ - inputctl->inheaders = 2; - break; - } - inputctl->inheaders = 0; - /* Note: start_input_pass must be called by jdmaster.c - * before any more input can be consumed. jdapimin.c is - * responsible for enforcing this sequencing. - */ + if (inputctl->inheaders == 1) + initial_setup(cinfo); + if (cinfo->comps_in_scan == 0) { /* pseudo SOS marker */ + inputctl->inheaders = 2; + break; + } + inputctl->inheaders = 0; + /* Note: start_input_pass must be called by jdmaster.c + * before any more input can be consumed. jdapimin.c is + * responsible for enforcing this sequencing. + */ } else { /* 2nd or later SOS marker */ - if (! inputctl->pub.has_multiple_scans) - ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ - if (cinfo->comps_in_scan == 0) /* unexpected pseudo SOS marker */ - break; - start_input_pass(cinfo); + if (! inputctl->pub.has_multiple_scans) + ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */ + if (cinfo->comps_in_scan == 0) /* unexpected pseudo SOS marker */ + break; + start_input_pass(cinfo); } return val; case JPEG_REACHED_EOI: /* Found EOI */ inputctl->pub.eoi_reached = TRUE; if (inputctl->inheaders) { /* Tables-only datastream, apparently */ - if (cinfo->marker->saw_SOF) - ERREXIT(cinfo, JERR_SOF_NO_SOS); + if (cinfo->marker->saw_SOF) + ERREXIT(cinfo, JERR_SOF_NO_SOS); } else { - /* Prevent infinite loop in coef ctlr's decompress_data routine - * if user set output_scan_number larger than number of scans. - */ - if (cinfo->output_scan_number > cinfo->input_scan_number) - cinfo->output_scan_number = cinfo->input_scan_number; + /* Prevent infinite loop in coef ctlr's decompress_data routine + * if user set output_scan_number larger than number of scans. + */ + if (cinfo->output_scan_number > cinfo->input_scan_number) + cinfo->output_scan_number = cinfo->input_scan_number; } return val; case JPEG_SUSPENDED: @@ -645,8 +646,8 @@ jinit_input_controller (j_decompress_ptr cinfo) /* Create subobject in permanent pool */ inputctl = (my_inputctl_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_input_controller)); - cinfo->inputctl = (struct jpeg_input_controller *) inputctl; + SIZEOF(my_input_controller)); + cinfo->inputctl = &inputctl->pub; /* Initialize method pointers */ inputctl->pub.consume_input = consume_markers; inputctl->pub.reset_input_controller = reset_input_controller; diff --git a/3rdparty/libjpeg/jdmainct.c b/3rdparty/libjpeg/jdmainct.c index 21829bfa36..52091fb2be 100644 --- a/3rdparty/libjpeg/jdmainct.c +++ b/3rdparty/libjpeg/jdmainct.c @@ -142,15 +142,15 @@ typedef my_main_controller * my_main_ptr; /* Forward declarations */ METHODDEF(void) process_data_simple_main - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); METHODDEF(void) process_data_context_main - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) process_data_crank_post - JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); + JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #endif @@ -171,7 +171,7 @@ alloc_funny_pointers (j_decompress_ptr cinfo) */ mainp->xbuffer[0] = (JSAMPIMAGE) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); + cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); mainp->xbuffer[1] = mainp->xbuffer[0] + cinfo->num_components; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; @@ -183,7 +183,7 @@ alloc_funny_pointers (j_decompress_ptr cinfo) */ xbuf = (JSAMPARRAY) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); + 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); xbuf += rgroup; /* want one row group at negative offsets */ mainp->xbuffer[0][ci] = xbuf; xbuf += rgroup * (M + 4); @@ -344,8 +344,8 @@ start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) METHODDEF(void) process_data_simple_main (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_main_ptr mainp = (my_main_ptr) cinfo->main; JDIMENSION rowgroups_avail; @@ -366,8 +366,8 @@ process_data_simple_main (j_decompress_ptr cinfo, /* Feed the postprocessor */ (*cinfo->post->post_process_data) (cinfo, mainp->buffer, - &mainp->rowgroup_ctr, rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); + &mainp->rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ if (mainp->rowgroup_ctr >= rowgroups_avail) { @@ -384,15 +384,15 @@ process_data_simple_main (j_decompress_ptr cinfo, METHODDEF(void) process_data_context_main (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_main_ptr mainp = (my_main_ptr) cinfo->main; /* Read input data if we haven't filled the main buffer yet */ if (! mainp->buffer_full) { if (! (*cinfo->coef->decompress_data) (cinfo, - mainp->xbuffer[mainp->whichptr])) + mainp->xbuffer[mainp->whichptr])) return; /* suspension forced, can do nothing more */ mainp->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ mainp->iMCU_row_ctr++; /* count rows received */ @@ -407,8 +407,8 @@ process_data_context_main (j_decompress_ptr cinfo, case CTX_POSTPONED_ROW: /* Call postprocessor using previously set pointers for postponed row */ (*cinfo->post->post_process_data) (cinfo, mainp->xbuffer[mainp->whichptr], - &mainp->rowgroup_ctr, mainp->rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); + &mainp->rowgroup_ctr, mainp->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); if (mainp->rowgroup_ctr < mainp->rowgroups_avail) return; /* Need to suspend */ mainp->context_state = CTX_PREPARE_FOR_IMCU; @@ -429,8 +429,8 @@ process_data_context_main (j_decompress_ptr cinfo, case CTX_PROCESS_IMCU: /* Call postprocessor using previously set pointers */ (*cinfo->post->post_process_data) (cinfo, mainp->xbuffer[mainp->whichptr], - &mainp->rowgroup_ctr, mainp->rowgroups_avail, - output_buf, out_row_ctr, out_rows_avail); + &mainp->rowgroup_ctr, mainp->rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); if (mainp->rowgroup_ctr < mainp->rowgroups_avail) return; /* Need to suspend */ /* After the first iMCU, change wraparound pointers to normal state */ @@ -458,12 +458,12 @@ process_data_context_main (j_decompress_ptr cinfo, METHODDEF(void) process_data_crank_post (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL, - (JDIMENSION *) NULL, (JDIMENSION) 0, - output_buf, out_row_ctr, out_rows_avail); + (JDIMENSION *) NULL, (JDIMENSION) 0, + output_buf, out_row_ctr, out_rows_avail); } #endif /* QUANT_2PASS_SUPPORTED */ @@ -482,7 +482,7 @@ jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) mainp = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_main_controller)); + SIZEOF(my_main_controller)); cinfo->main = &mainp->pub; mainp->pub.start_pass = start_pass_main; diff --git a/3rdparty/libjpeg/jdmarker.c b/3rdparty/libjpeg/jdmarker.c index d3fe5145fe..3fbe5c1657 100644 --- a/3rdparty/libjpeg/jdmarker.c +++ b/3rdparty/libjpeg/jdmarker.c @@ -2,7 +2,7 @@ * jdmarker.c * * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2009-2012 by Guido Vollbeding. + * Modified 2009-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -119,49 +119,49 @@ typedef my_marker_reader * my_marker_ptr; /* Declare and initialize local copies of input pointer/count */ #define INPUT_VARS(cinfo) \ - struct jpeg_source_mgr * datasrc = (cinfo)->src; \ - const JOCTET * next_input_byte = datasrc->next_input_byte; \ - size_t bytes_in_buffer = datasrc->bytes_in_buffer + struct jpeg_source_mgr * datasrc = (cinfo)->src; \ + const JOCTET * next_input_byte = datasrc->next_input_byte; \ + size_t bytes_in_buffer = datasrc->bytes_in_buffer /* Unload the local copies --- do this only at a restart boundary */ #define INPUT_SYNC(cinfo) \ - ( datasrc->next_input_byte = next_input_byte, \ - datasrc->bytes_in_buffer = bytes_in_buffer ) + ( datasrc->next_input_byte = next_input_byte, \ + datasrc->bytes_in_buffer = bytes_in_buffer ) /* Reload the local copies --- used only in MAKE_BYTE_AVAIL */ #define INPUT_RELOAD(cinfo) \ - ( next_input_byte = datasrc->next_input_byte, \ - bytes_in_buffer = datasrc->bytes_in_buffer ) + ( next_input_byte = datasrc->next_input_byte, \ + bytes_in_buffer = datasrc->bytes_in_buffer ) /* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, * but we must reload the local copies after a successful fill. */ #define MAKE_BYTE_AVAIL(cinfo,action) \ - if (bytes_in_buffer == 0) { \ - if (! (*datasrc->fill_input_buffer) (cinfo)) \ - { action; } \ - INPUT_RELOAD(cinfo); \ - } + if (bytes_in_buffer == 0) { \ + if (! (*datasrc->fill_input_buffer) (cinfo)) \ + { action; } \ + INPUT_RELOAD(cinfo); \ + } /* Read a byte into variable V. * If must suspend, take the specified action (typically "return FALSE"). */ #define INPUT_BYTE(cinfo,V,action) \ - MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = GETJOCTET(*next_input_byte++); ) + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) /* As above, but read two bytes interpreted as an unsigned 16-bit integer. * V should be declared unsigned int or perhaps INT32. */ #define INPUT_2BYTES(cinfo,V,action) \ - MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ - MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V += GETJOCTET(*next_input_byte++); ) + MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo,action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) /* @@ -200,7 +200,7 @@ get_soi (j_decompress_ptr cinfo) /* Process an SOI marker */ { int i; - + TRACEMS(cinfo, 1, JTRC_SOI); if (cinfo->marker->saw_SOI) @@ -238,7 +238,7 @@ get_soi (j_decompress_ptr cinfo) LOCAL(boolean) get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, - boolean is_arith) + boolean is_arith) /* Process a SOFn marker */ { INT32 length; @@ -260,8 +260,8 @@ get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, length -= 8; TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, - (int) cinfo->image_width, (int) cinfo->image_height, - cinfo->num_components); + (int) cinfo->image_width, (int) cinfo->image_height, + cinfo->num_components); if (cinfo->marker->saw_SOF) ERREXIT(cinfo, JERR_SOF_DUPLICATE); @@ -269,8 +269,8 @@ get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, /* We don't support files in which the image height is initially specified */ /* as 0 and is later redefined by DNL. As long as we have to check that, */ /* might as well have a general sanity check. */ - if (cinfo->image_height <= 0 || cinfo->image_width <= 0 - || cinfo->num_components <= 0) + if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || + cinfo->num_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); if (length != (cinfo->num_components * 3)) @@ -278,8 +278,8 @@ get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, if (cinfo->comp_info == NULL) /* do only once, even if suspend */ cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->num_components * SIZEOF(jpeg_component_info)); + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->num_components * SIZEOF(jpeg_component_info)); for (ci = 0; ci < cinfo->num_components; ci++) { INPUT_BYTE(cinfo, c, return FALSE); @@ -289,14 +289,14 @@ get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, /* max id seen so far + 1. */ for (i = 0, compptr = cinfo->comp_info; i < ci; i++, compptr++) { if (c == compptr->component_id) { - compptr = cinfo->comp_info; - c = compptr->component_id; - compptr++; - for (i = 1; i < ci; i++, compptr++) { - if (compptr->component_id > c) c = compptr->component_id; - } - c++; - break; + compptr = cinfo->comp_info; + c = compptr->component_id; + compptr++; + for (i = 1; i < ci; i++, compptr++) { + if (compptr->component_id > c) c = compptr->component_id; + } + c++; + break; } } compptr->component_id = c; @@ -307,8 +307,8 @@ get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, - compptr->component_id, compptr->h_samp_factor, - compptr->v_samp_factor, compptr->quant_tbl_no); + compptr->component_id, compptr->h_samp_factor, + compptr->v_samp_factor, compptr->quant_tbl_no); } cinfo->marker->saw_SOF = TRUE; @@ -350,22 +350,25 @@ get_sos (j_decompress_ptr cinfo) /* Detect the case where component id's are not unique, and, if so, */ /* create a fake component id using the same logic as in get_sof. */ + /* Note: This also ensures that all of the SOF components are */ + /* referenced in the single scan case, which prevents access to */ + /* uninitialized memory in later decoding stages. */ for (ci = 0; ci < i; ci++) { if (c == cinfo->cur_comp_info[ci]->component_id) { - c = cinfo->cur_comp_info[0]->component_id; - for (ci = 1; ci < i; ci++) { - compptr = cinfo->cur_comp_info[ci]; - if (compptr->component_id > c) c = compptr->component_id; - } - c++; - break; + c = cinfo->cur_comp_info[0]->component_id; + for (ci = 1; ci < i; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (compptr->component_id > c) c = compptr->component_id; + } + c++; + break; } } for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { + ci++, compptr++) { if (c == compptr->component_id) - goto id_found; + goto id_found; } ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, c); @@ -378,7 +381,7 @@ get_sos (j_decompress_ptr cinfo) compptr->ac_tbl_no = (c ) & 15; TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, compptr->component_id, - compptr->dc_tbl_no, compptr->ac_tbl_no); + compptr->dc_tbl_no, compptr->ac_tbl_no); } /* Collect the additional scan parameters Ss, Se, Ah/Al. */ @@ -391,7 +394,7 @@ get_sos (j_decompress_ptr cinfo) cinfo->Al = (c ) & 15; TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se, - cinfo->Ah, cinfo->Al); + cinfo->Ah, cinfo->Al); /* Prepare to scan data & restart markers */ cinfo->marker->next_restart_num = 0; @@ -416,7 +419,7 @@ get_dac (j_decompress_ptr cinfo) INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; - + while (length > 0) { INPUT_BYTE(cinfo, index, return FALSE); INPUT_BYTE(cinfo, val, return FALSE); @@ -434,7 +437,7 @@ get_dac (j_decompress_ptr cinfo) cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); cinfo->arith_dc_U[index] = (UINT8) (val >> 4); if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) - ERREXIT1(cinfo, JERR_DAC_VALUE, val); + ERREXIT1(cinfo, JERR_DAC_VALUE, val); } } @@ -465,12 +468,12 @@ get_dht (j_decompress_ptr cinfo) INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; - + while (length > 16) { INPUT_BYTE(cinfo, index, return FALSE); TRACEMS1(cinfo, 1, JTRC_DHT, index); - + bits[0] = 0; count = 0; for (i = 1; i <= 16; i++) { @@ -481,11 +484,11 @@ get_dht (j_decompress_ptr cinfo) length -= 1 + 16; TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[1], bits[2], bits[3], bits[4], - bits[5], bits[6], bits[7], bits[8]); + bits[1], bits[2], bits[3], bits[4], + bits[5], bits[6], bits[7], bits[8]); TRACEMS8(cinfo, 2, JTRC_HUFFBITS, - bits[9], bits[10], bits[11], bits[12], - bits[13], bits[14], bits[15], bits[16]); + bits[9], bits[10], bits[11], bits[12], + bits[13], bits[14], bits[15], bits[16]); /* Here we just do minimal validation of the counts to avoid walking * off the end of our table space. jdhuff.c will check more carefully. @@ -493,6 +496,8 @@ get_dht (j_decompress_ptr cinfo) if (count > 256 || ((INT32) count) > length) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); + MEMZERO(huffval, SIZEOF(huffval)); /* pre-zero array for later copy */ + for (i = 0; i < count; i++) INPUT_BYTE(cinfo, huffval[i], return FALSE); @@ -510,7 +515,7 @@ get_dht (j_decompress_ptr cinfo) if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - + MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); } @@ -547,29 +552,29 @@ get_dqt (j_decompress_ptr cinfo) if (n >= NUM_QUANT_TBLS) ERREXIT1(cinfo, JERR_DQT_INDEX, n); - + if (cinfo->quant_tbl_ptrs[n] == NULL) cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); quant_ptr = cinfo->quant_tbl_ptrs[n]; if (prec) { if (length < DCTSIZE2 * 2) { - /* Initialize full table for safety. */ - for (i = 0; i < DCTSIZE2; i++) { - quant_ptr->quantval[i] = 1; - } - count = length >> 1; + /* Initialize full table for safety. */ + for (i = 0; i < DCTSIZE2; i++) { + quant_ptr->quantval[i] = 1; + } + count = length >> 1; } else - count = DCTSIZE2; + count = DCTSIZE2; } else { if (length < DCTSIZE2) { - /* Initialize full table for safety. */ - for (i = 0; i < DCTSIZE2; i++) { - quant_ptr->quantval[i] = 1; - } - count = length; + /* Initialize full table for safety. */ + for (i = 0; i < DCTSIZE2; i++) { + quant_ptr->quantval[i] = 1; + } + count = length; } else - count = DCTSIZE2; + count = DCTSIZE2; } switch (count) { @@ -584,20 +589,20 @@ get_dqt (j_decompress_ptr cinfo) for (i = 0; i < count; i++) { if (prec) - INPUT_2BYTES(cinfo, tmp, return FALSE); + INPUT_2BYTES(cinfo, tmp, return FALSE); else - INPUT_BYTE(cinfo, tmp, return FALSE); + INPUT_BYTE(cinfo, tmp, return FALSE); /* We convert the zigzag-order table to natural array order. */ quant_ptr->quantval[natural_order[i]] = (UINT16) tmp; } if (cinfo->err->trace_level >= 2) { for (i = 0; i < DCTSIZE2; i += 8) { - TRACEMS8(cinfo, 2, JTRC_QUANTVALS, - quant_ptr->quantval[i], quant_ptr->quantval[i+1], - quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], - quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], - quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); + TRACEMS8(cinfo, 2, JTRC_QUANTVALS, + quant_ptr->quantval[i], quant_ptr->quantval[i+1], + quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], + quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], + quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); } } @@ -622,7 +627,7 @@ get_dri (j_decompress_ptr cinfo) INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); - + if (length != 4) ERREXIT(cinfo, JERR_BAD_LENGTH); @@ -713,7 +718,7 @@ get_lse (j_decompress_ptr cinfo) LOCAL(void) examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, - unsigned int datalen, INT32 remaining) + unsigned int datalen, INT32 remaining) /* Examine first few bytes from an APP0. * Take appropriate action if it is a JFIF marker. * datalen is # of bytes at data[], remaining is length of rest of marker data. @@ -735,25 +740,26 @@ examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]); cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]); /* Check version. - * Major version must be 1, anything else signals an incompatible change. + * Major version must be 1 or 2, anything else signals an incompatible + * change. * (We used to treat this as an error, but now it's a nonfatal warning, * because some bozo at Hijaak couldn't read the spec.) * Minor version should be 0..2, but process anyway if newer. */ - if (cinfo->JFIF_major_version != 1) + if (cinfo->JFIF_major_version != 1 && cinfo->JFIF_major_version != 2) WARNMS2(cinfo, JWRN_JFIF_MAJOR, - cinfo->JFIF_major_version, cinfo->JFIF_minor_version); + cinfo->JFIF_major_version, cinfo->JFIF_minor_version); /* Generate trace messages */ TRACEMS5(cinfo, 1, JTRC_JFIF, - cinfo->JFIF_major_version, cinfo->JFIF_minor_version, - cinfo->X_density, cinfo->Y_density, cinfo->density_unit); + cinfo->JFIF_major_version, cinfo->JFIF_minor_version, + cinfo->X_density, cinfo->Y_density, cinfo->density_unit); /* Validate thumbnail dimensions and issue appropriate messages */ if (GETJOCTET(data[12]) | GETJOCTET(data[13])) TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, - GETJOCTET(data[12]), GETJOCTET(data[13])); + GETJOCTET(data[12]), GETJOCTET(data[13])); totallen -= APP0_DATA_LEN; if (totallen != - ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) + ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3)) TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen); } else if (datalen >= 6 && GETJOCTET(data[0]) == 0x4A && @@ -777,7 +783,7 @@ examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, break; default: TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION, - GETJOCTET(data[5]), (int) totallen); + GETJOCTET(data[5]), (int) totallen); break; } } else { @@ -789,7 +795,7 @@ examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, LOCAL(void) examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data, - unsigned int datalen, INT32 remaining) + unsigned int datalen, INT32 remaining) /* Examine first few bytes from an APP14. * Take appropriate action if it is an Adobe marker. * datalen is # of bytes at data[], remaining is length of rest of marker data. @@ -885,15 +891,15 @@ save_marker (j_decompress_ptr cinfo) /* figure out how much we want to save */ unsigned int limit; if (cinfo->unread_marker == (int) M_COM) - limit = marker->length_limit_COM; + limit = marker->length_limit_COM; else - limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; + limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0]; if ((unsigned int) length < limit) - limit = (unsigned int) length; + limit = (unsigned int) length; /* allocate and initialize the marker item */ cur_marker = (jpeg_saved_marker_ptr) - (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(struct jpeg_marker_struct) + limit); + (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, + SIZEOF(struct jpeg_marker_struct) + limit); cur_marker->next = NULL; cur_marker->marker = (UINT8) cinfo->unread_marker; cur_marker->original_length = (unsigned int) length; @@ -937,7 +943,7 @@ save_marker (j_decompress_ptr cinfo) } else { jpeg_saved_marker_ptr prev = cinfo->marker_list; while (prev->next != NULL) - prev = prev->next; + prev = prev->next; prev->next = cur_marker; } /* Reset pointer & calc remaining data length */ @@ -957,7 +963,7 @@ save_marker (j_decompress_ptr cinfo) break; default: TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, - (int) (data_length + length)); + (int) (data_length + length)); break; } @@ -981,7 +987,7 @@ skip_variable (j_decompress_ptr cinfo) INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; - + TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); INPUT_SYNC(cinfo); /* do before skip_input_data */ @@ -1093,11 +1099,11 @@ read_markers (j_decompress_ptr cinfo) /* NB: first_marker() enforces the requirement that SOI appear first. */ if (cinfo->unread_marker == 0) { if (! cinfo->marker->saw_SOI) { - if (! first_marker(cinfo)) - return JPEG_SUSPENDED; + if (! first_marker(cinfo)) + return JPEG_SUSPENDED; } else { - if (! next_marker(cinfo)) - return JPEG_SUSPENDED; + if (! next_marker(cinfo)) + return JPEG_SUSPENDED; } } /* At this point cinfo->unread_marker contains the marker code and the @@ -1107,32 +1113,32 @@ read_markers (j_decompress_ptr cinfo) switch (cinfo->unread_marker) { case M_SOI: if (! get_soi(cinfo)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; case M_SOF0: /* Baseline */ if (! get_sof(cinfo, TRUE, FALSE, FALSE)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; case M_SOF1: /* Extended sequential, Huffman */ if (! get_sof(cinfo, FALSE, FALSE, FALSE)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; case M_SOF2: /* Progressive, Huffman */ if (! get_sof(cinfo, FALSE, TRUE, FALSE)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; case M_SOF9: /* Extended sequential, arithmetic */ if (! get_sof(cinfo, FALSE, FALSE, TRUE)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; case M_SOF10: /* Progressive, arithmetic */ if (! get_sof(cinfo, FALSE, TRUE, TRUE)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; /* Currently unsupported SOFn types */ @@ -1150,7 +1156,7 @@ read_markers (j_decompress_ptr cinfo) case M_SOS: if (! get_sos(cinfo)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; cinfo->unread_marker = 0; /* processed the marker */ return JPEG_REACHED_SOS; @@ -1161,27 +1167,27 @@ read_markers (j_decompress_ptr cinfo) case M_DAC: if (! get_dac(cinfo)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; case M_DHT: if (! get_dht(cinfo)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; case M_DQT: if (! get_dqt(cinfo)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; case M_DRI: if (! get_dri(cinfo)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; case M_JPG8: if (! get_lse(cinfo)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; case M_APP0: @@ -1201,13 +1207,13 @@ read_markers (j_decompress_ptr cinfo) case M_APP14: case M_APP15: if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[ - cinfo->unread_marker - (int) M_APP0]) (cinfo)) - return JPEG_SUSPENDED; + cinfo->unread_marker - (int) M_APP0]) (cinfo)) + return JPEG_SUSPENDED; break; case M_COM: if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; case M_RST0: /* these are all parameterless */ @@ -1224,7 +1230,7 @@ read_markers (j_decompress_ptr cinfo) case M_DNL: /* Ignore DNL ... perhaps the wrong thing */ if (! skip_variable(cinfo)) - return JPEG_SUSPENDED; + return JPEG_SUSPENDED; break; default: /* must be DHP, EXP, JPGn, or RESn */ @@ -1273,7 +1279,7 @@ read_restart_marker (j_decompress_ptr cinfo) /* Uh-oh, the restart markers have been messed up. */ /* Let the data source manager determine how to resync. */ if (! (*cinfo->src->resync_to_restart) (cinfo, - cinfo->marker->next_restart_num)) + cinfo->marker->next_restart_num)) return FALSE; } @@ -1338,10 +1344,10 @@ jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) { int marker = cinfo->unread_marker; int action = 1; - + /* Always put up a warning. */ WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); - + /* Outer loop handles repeated decision after scanning forward. */ for (;;) { if (marker < (int) M_SOF0) @@ -1350,13 +1356,13 @@ jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) action = 3; /* valid non-restart marker */ else { if (marker == ((int) M_RST0 + ((desired+1) & 7)) || - marker == ((int) M_RST0 + ((desired+2) & 7))) - action = 3; /* one of the next two expected restarts */ + marker == ((int) M_RST0 + ((desired+2) & 7))) + action = 3; /* one of the next two expected restarts */ else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || - marker == ((int) M_RST0 + ((desired-2) & 7))) - action = 2; /* a prior restart, so advance */ + marker == ((int) M_RST0 + ((desired-2) & 7))) + action = 2; /* a prior restart, so advance */ else - action = 1; /* desired restart or too far away */ + action = 1; /* desired restart or too far away */ } TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); switch (action) { @@ -1367,7 +1373,7 @@ jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired) case 2: /* Scan to the next marker, and repeat the decision loop. */ if (! next_marker(cinfo)) - return FALSE; + return FALSE; marker = cinfo->unread_marker; break; case 3: @@ -1412,7 +1418,7 @@ jinit_marker_reader (j_decompress_ptr cinfo) /* Create subobject in permanent pool */ marker = (my_marker_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - SIZEOF(my_marker_reader)); + SIZEOF(my_marker_reader)); cinfo->marker = &marker->pub; /* Initialize public method pointers */ marker->pub.reset_marker_reader = reset_marker_reader; @@ -1443,7 +1449,7 @@ jinit_marker_reader (j_decompress_ptr cinfo) GLOBAL(void) jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, - unsigned int length_limit) + unsigned int length_limit) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; long maxlength; @@ -1492,7 +1498,7 @@ jpeg_save_markers (j_decompress_ptr cinfo, int marker_code, GLOBAL(void) jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine) + jpeg_marker_parser_method routine) { my_marker_ptr marker = (my_marker_ptr) cinfo->marker; diff --git a/3rdparty/libjpeg/jdmaster.c b/3rdparty/libjpeg/jdmaster.c index 6c9b1667f6..ab95090f4d 100644 --- a/3rdparty/libjpeg/jdmaster.c +++ b/3rdparty/libjpeg/jdmaster.c @@ -2,7 +2,7 @@ * jdmaster.c * * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2002-2011 by Guido Vollbeding. + * Modified 2002-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -45,13 +45,26 @@ LOCAL(boolean) use_merged_upsample (j_decompress_ptr cinfo) { #ifdef UPSAMPLE_MERGING_SUPPORTED - /* Merging is the equivalent of plain box-filter upsampling */ - if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling) + /* Merging is the equivalent of plain box-filter upsampling. */ + /* The following condition is only needed if fancy shall select + * a different upsampling method. In our current implementation + * fancy only affects the DCT scaling, thus we can use fancy + * upsampling and merged upsample simultaneously, in particular + * with scaled DCT sizes larger than the default DCTSIZE. + */ +#if 0 + if (cinfo->do_fancy_upsampling) + return FALSE; +#endif + if (cinfo->CCIR601_sampling) return FALSE; /* jdmerge.c only supports YCC=>RGB color conversion */ - if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 || + if ((cinfo->jpeg_color_space != JCS_YCbCr && + cinfo->jpeg_color_space != JCS_BG_YCC) || + cinfo->num_components != 3 || cinfo->out_color_space != JCS_RGB || - cinfo->out_color_components != RGB_PIXELSIZE) + cinfo->out_color_components != RGB_PIXELSIZE || + cinfo->color_transform) return FALSE; /* and it only handles 2h1v or 2h2v sampling ratios */ if (cinfo->comp_info[0].h_samp_factor != 2 || @@ -113,24 +126,24 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo) ci++, compptr++) { int ssize = 1; while (cinfo->min_DCT_h_scaled_size * ssize <= - (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && - (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { + (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) { ssize = ssize * 2; } compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize; ssize = 1; while (cinfo->min_DCT_v_scaled_size * ssize <= - (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && - (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { + (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) && + (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) { ssize = ssize * 2; } compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize; /* We don't support IDCT ratios larger than 2. */ if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2) - compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; + compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2; else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2) - compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; + compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2; } /* Recompute downsampled dimensions of components; @@ -141,12 +154,12 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo) /* Size in samples, after IDCT scaling */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * - (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), - (long) (cinfo->max_h_samp_factor * cinfo->block_size)); + (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size), + (long) (cinfo->max_h_samp_factor * cinfo->block_size)); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * - (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size), + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); } #endif /* IDCT_SCALING_SUPPORTED */ @@ -158,9 +171,11 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo) cinfo->out_color_components = 1; break; case JCS_RGB: + case JCS_BG_RGB: cinfo->out_color_components = RGB_PIXELSIZE; break; case JCS_YCbCr: + case JCS_BG_YCC: cinfo->out_color_components = 3; break; case JCS_CMYK: @@ -172,7 +187,7 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo) break; } cinfo->output_components = (cinfo->quantize_colors ? 1 : - cinfo->out_color_components); + cinfo->out_color_components); /* See if upsampler will want to emit more than one row at a time */ if (use_merged_upsample(cinfo)) @@ -196,30 +211,20 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo) * These processes all use a common table prepared by the routine below. * * For most steps we can mathematically guarantee that the initial value - * of x is within MAXJSAMPLE+1 of the legal range, so a table running from - * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial - * limiting step (just after the IDCT), a wildly out-of-range value is - * possible if the input data is corrupt. To avoid any chance of indexing + * of x is within 2*(MAXJSAMPLE+1) of the legal range, so a table running + * from -2*(MAXJSAMPLE+1) to 3*MAXJSAMPLE+2 is sufficient. But for the + * initial limiting step (just after the IDCT), a wildly out-of-range value + * is possible if the input data is corrupt. To avoid any chance of indexing * off the end of memory and getting a bad-pointer trap, we perform the * post-IDCT limiting thus: - * x = range_limit[x & MASK]; + * x = (sample_range_limit - SUBSET)[(x + CENTER) & MASK]; * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit * samples. Under normal circumstances this is more than enough range and * a correct output will be generated; with bogus input data the mask will * cause wraparound, and we will safely generate a bogus-but-in-range output. * For the post-IDCT step, we want to convert the data from signed to unsigned * representation by adding CENTERJSAMPLE at the same time that we limit it. - * So the post-IDCT limiting table ends up looking like this: - * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, - * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), - * 0,1,...,CENTERJSAMPLE-1 - * Negative inputs select values from the upper half of the table after - * masking. - * - * We can save some space by overlapping the start of the post-IDCT table - * with the simpler range limiting table. The post-IDCT table begins at - * sample_range_limit + CENTERJSAMPLE. + * This is accomplished with SUBSET = CENTER - CENTERJSAMPLE. * * Note that the table is allocated in near data space on PCs; it's small * enough and used often enough to justify this. @@ -234,23 +239,17 @@ prepare_range_limit_table (j_decompress_ptr cinfo) table = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); - table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ + 5 * (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + /* First segment of range limit table: limit[x] = 0 for x < 0 */ + MEMZERO(table, 2 * (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + table += 2 * (MAXJSAMPLE+1); /* allow negative subscripts of table */ cinfo->sample_range_limit = table; - /* First segment of "simple" table: limit[x] = 0 for x < 0 */ - MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); - /* Main part of "simple" table: limit[x] = x */ + /* Main part of range limit table: limit[x] = x */ for (i = 0; i <= MAXJSAMPLE; i++) table[i] = (JSAMPLE) i; - table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ - /* End of simple table, rest of first half of post-IDCT table */ - for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) + /* End of range limit table: limit[x] = MAXJSAMPLE for x > MAXJSAMPLE */ + for (; i < 3 * (MAXJSAMPLE+1); i++) table[i] = MAXJSAMPLE; - /* Second half of post-IDCT table */ - MEMZERO(table + (2 * (MAXJSAMPLE+1)), - (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); - MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), - cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); } @@ -273,10 +272,19 @@ master_selection (j_decompress_ptr cinfo) long samplesperrow; JDIMENSION jd_samplesperrow; + /* For now, precision must match compiled-in value... */ + if (cinfo->data_precision != BITS_IN_JSAMPLE) + ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); + /* Initialize dimensions and other stuff */ jpeg_calc_output_dimensions(cinfo); prepare_range_limit_table(cinfo); + /* Sanity check on image dimensions */ + if (cinfo->output_height <= 0 || cinfo->output_width <= 0 || + cinfo->out_color_components <= 0) + ERREXIT(cinfo, JERR_EMPTY_IMAGE); + /* Width of an output scanline must be representable as JDIMENSION. */ samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; jd_samplesperrow = (JDIMENSION) samplesperrow; @@ -427,24 +435,24 @@ prepare_for_output_pass (j_decompress_ptr cinfo) if (cinfo->quantize_colors && cinfo->colormap == NULL) { /* Select new quantization method */ if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) { - cinfo->cquantize = master->quantizer_2pass; - master->pub.is_dummy_pass = TRUE; + cinfo->cquantize = master->quantizer_2pass; + master->pub.is_dummy_pass = TRUE; } else if (cinfo->enable_1pass_quant) { - cinfo->cquantize = master->quantizer_1pass; + cinfo->cquantize = master->quantizer_1pass; } else { - ERREXIT(cinfo, JERR_MODE_CHANGE); + ERREXIT(cinfo, JERR_MODE_CHANGE); } } (*cinfo->idct->start_pass) (cinfo); (*cinfo->coef->start_output_pass) (cinfo); if (! cinfo->raw_data_out) { if (! master->using_merged_upsample) - (*cinfo->cconvert->start_pass) (cinfo); + (*cinfo->cconvert->start_pass) (cinfo); (*cinfo->upsample->start_pass) (cinfo); if (cinfo->quantize_colors) - (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); + (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass); (*cinfo->post->start_pass) (cinfo, - (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); + (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); } } @@ -453,7 +461,7 @@ prepare_for_output_pass (j_decompress_ptr cinfo) if (cinfo->progress != NULL) { cinfo->progress->completed_passes = master->pass_number; cinfo->progress->total_passes = master->pass_number + - (master->pub.is_dummy_pass ? 2 : 1); + (master->pub.is_dummy_pass ? 2 : 1); /* In buffered-image mode, we assume one more output pass if EOI not * yet reached, but no more passes if EOI has been reached. */ @@ -520,8 +528,8 @@ jinit_master_decompress (j_decompress_ptr cinfo) master = (my_master_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_decomp_master)); - cinfo->master = (struct jpeg_decomp_master *) master; + SIZEOF(my_decomp_master)); + cinfo->master = &master->pub; master->pub.prepare_for_output_pass = prepare_for_output_pass; master->pub.finish_output_pass = finish_output_pass; diff --git a/3rdparty/libjpeg/jdmerge.c b/3rdparty/libjpeg/jdmerge.c index 170bed1a5d..192da5829d 100644 --- a/3rdparty/libjpeg/jdmerge.c +++ b/3rdparty/libjpeg/jdmerge.c @@ -2,6 +2,7 @@ * jdmerge.c * * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2013-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -23,7 +24,7 @@ * multiplications needed for color conversion. * * This file currently provides implementations for the following cases: - * YCbCr => RGB color conversion only. + * YCC => RGB color conversion only (YCbCr or BG_YCC). * Sampling ratios of 2h1v or 2h2v. * No scaling needed at upsample time. * Corner-aligned (non-CCIR601) sampling alignment. @@ -46,8 +47,8 @@ typedef struct { /* Pointer to routine to do actual upsampling/conversion of one row group */ JMETHOD(void, upmethod, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf)); + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf)); /* Private state for YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ @@ -75,12 +76,13 @@ typedef my_upsampler * my_upsample_ptr; /* - * Initialize tables for YCC->RGB colorspace conversion. + * Initialize tables for YCbCr->RGB and BG_YCC->RGB colorspace conversion. * This is taken directly from jdcolor.c; see that file for more info. */ LOCAL(void) build_ycc_rgb_table (j_decompress_ptr cinfo) +/* Normal case, sYCC */ { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; int i; @@ -89,31 +91,71 @@ build_ycc_rgb_table (j_decompress_ptr cinfo) upsample->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); + (MAXJSAMPLE+1) * SIZEOF(int)); upsample->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(int)); + (MAXJSAMPLE+1) * SIZEOF(int)); upsample->Cr_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); + (MAXJSAMPLE+1) * SIZEOF(INT32)); upsample->Cb_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (MAXJSAMPLE+1) * SIZEOF(INT32)); + (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>R value is nearest int to 1.40200 * x */ + /* Cr=>R value is nearest int to 1.402 * x */ upsample->Cr_r_tab[i] = (int) - RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); - /* Cb=>B value is nearest int to 1.77200 * x */ + RIGHT_SHIFT(FIX(1.402) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 1.772 * x */ upsample->Cb_b_tab[i] = (int) - RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); - /* Cr=>G value is scaled-up -0.71414 * x */ - upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; - /* Cb=>G value is scaled-up -0.34414 * x */ + RIGHT_SHIFT(FIX(1.772) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -0.714136286 * x */ + upsample->Cr_g_tab[i] = (- FIX(0.714136286)) * x; + /* Cb=>G value is scaled-up -0.344136286 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ - upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; + upsample->Cb_g_tab[i] = (- FIX(0.344136286)) * x + ONE_HALF; + } +} + + +LOCAL(void) +build_bg_ycc_rgb_table (j_decompress_ptr cinfo) +/* Wide gamut case, bg-sYCC */ +{ + my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; + int i; + INT32 x; + SHIFT_TEMPS + + upsample->Cr_r_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cb_b_tab = (int *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)); + upsample->Cr_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + upsample->Cb_g_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)); + + for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { + /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ + /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ + /* Cr=>R value is nearest int to 2.804 * x */ + upsample->Cr_r_tab[i] = (int) + RIGHT_SHIFT(FIX(2.804) * x + ONE_HALF, SCALEBITS); + /* Cb=>B value is nearest int to 3.544 * x */ + upsample->Cb_b_tab[i] = (int) + RIGHT_SHIFT(FIX(3.544) * x + ONE_HALF, SCALEBITS); + /* Cr=>G value is scaled-up -1.428272572 * x */ + upsample->Cr_g_tab[i] = (- FIX(1.428272572)) * x; + /* Cb=>G value is scaled-up -0.688272572 * x */ + /* We also add in ONE_HALF so that need not do it in inner loop */ + upsample->Cb_g_tab[i] = (- FIX(0.688272572)) * x + ONE_HALF; } } @@ -142,10 +184,10 @@ start_pass_merged_upsample (j_decompress_ptr cinfo) METHODDEF(void) merged_2v_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) /* 2:1 vertical sampling case: may need a spare row. */ { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; @@ -155,7 +197,7 @@ merged_2v_upsample (j_decompress_ptr cinfo, if (upsample->spare_full) { /* If we have a spare row saved from a previous cycle, just return it. */ jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, - 1, upsample->out_row_width); + 1, upsample->out_row_width); num_rows = 1; upsample->spare_full = FALSE; } else { @@ -191,17 +233,17 @@ merged_2v_upsample (j_decompress_ptr cinfo, METHODDEF(void) merged_1v_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) /* 1:1 vertical sampling case: much easier, never need a spare row. */ { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; /* Just do the upsampling. */ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, - output_buf + *out_row_ctr); + output_buf + *out_row_ctr); /* Adjust counts */ (*out_row_ctr)++; (*in_row_group_ctr)++; @@ -224,8 +266,8 @@ merged_1v_upsample (j_decompress_ptr cinfo, METHODDEF(void) h2v1_merged_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; register int y, cred, cgreen, cblue; @@ -250,32 +292,32 @@ h2v1_merged_upsample (j_decompress_ptr cinfo, /* Do the chroma part of the calculation */ cb = GETJSAMPLE(*inptr1++); cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; + cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; + cblue = Cbbtab[cb]; /* Fetch 2 Y values and emit 2 pixels */ y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_RED] = range_limit[y + cred]; outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr[RGB_BLUE] = range_limit[y + cblue]; outptr += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr0++); - outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_RED] = range_limit[y + cred]; outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr[RGB_BLUE] = range_limit[y + cblue]; outptr += RGB_PIXELSIZE; } /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { cb = GETJSAMPLE(*inptr1); cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; + cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; + cblue = Cbbtab[cb]; y = GETJSAMPLE(*inptr0); - outptr[RGB_RED] = range_limit[y + cred]; + outptr[RGB_RED] = range_limit[y + cred]; outptr[RGB_GREEN] = range_limit[y + cgreen]; - outptr[RGB_BLUE] = range_limit[y + cblue]; + outptr[RGB_BLUE] = range_limit[y + cblue]; } } @@ -286,8 +328,8 @@ h2v1_merged_upsample (j_decompress_ptr cinfo, METHODDEF(void) h2v2_merged_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, - JSAMPARRAY output_buf) + JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, + JSAMPARRAY output_buf) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; register int y, cred, cgreen, cblue; @@ -314,46 +356,46 @@ h2v2_merged_upsample (j_decompress_ptr cinfo, /* Do the chroma part of the calculation */ cb = GETJSAMPLE(*inptr1++); cr = GETJSAMPLE(*inptr2++); - cred = Crrtab[cr]; + cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; + cblue = Cbbtab[cb]; /* Fetch 4 Y values and emit 4 pixels */ y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; outptr0 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr00++); - outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; outptr0 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; outptr1 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr01++); - outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; outptr1 += RGB_PIXELSIZE; } /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { cb = GETJSAMPLE(*inptr1); cr = GETJSAMPLE(*inptr2); - cred = Crrtab[cr]; + cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); - cblue = Cbbtab[cb]; + cblue = Cbbtab[cb]; y = GETJSAMPLE(*inptr00); - outptr0[RGB_RED] = range_limit[y + cred]; + outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; - outptr0[RGB_BLUE] = range_limit[y + cblue]; + outptr0[RGB_BLUE] = range_limit[y + cblue]; y = GETJSAMPLE(*inptr01); - outptr1[RGB_RED] = range_limit[y + cred]; + outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; - outptr1[RGB_BLUE] = range_limit[y + cblue]; + outptr1[RGB_BLUE] = range_limit[y + cblue]; } } @@ -373,8 +415,8 @@ jinit_merged_upsampler (j_decompress_ptr cinfo) upsample = (my_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_upsampler)); - cinfo->upsample = (struct jpeg_upsampler *) upsample; + SIZEOF(my_upsampler)); + cinfo->upsample = &upsample->pub; upsample->pub.start_pass = start_pass_merged_upsample; upsample->pub.need_context_rows = FALSE; @@ -386,7 +428,7 @@ jinit_merged_upsampler (j_decompress_ptr cinfo) /* Allocate a spare row buffer */ upsample->spare_row = (JSAMPROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); + (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); } else { upsample->pub.upsample = merged_1v_upsample; upsample->upmethod = h2v1_merged_upsample; @@ -394,7 +436,10 @@ jinit_merged_upsampler (j_decompress_ptr cinfo) upsample->spare_row = NULL; } - build_ycc_rgb_table(cinfo); + if (cinfo->jpeg_color_space == JCS_BG_YCC) + build_bg_ycc_rgb_table(cinfo); + else + build_ycc_rgb_table(cinfo); } #endif /* UPSAMPLE_MERGING_SUPPORTED */ diff --git a/3rdparty/libjpeg/jdpostct.c b/3rdparty/libjpeg/jdpostct.c index 48215ef86f..571563d728 100644 --- a/3rdparty/libjpeg/jdpostct.c +++ b/3rdparty/libjpeg/jdpostct.c @@ -44,24 +44,24 @@ typedef my_post_controller * my_post_ptr; /* Forward declarations */ METHODDEF(void) post_process_1pass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); #ifdef QUANT_2PASS_SUPPORTED METHODDEF(void) post_process_prepass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); METHODDEF(void) post_process_2pass - JPP((j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); + JPP((j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); #endif @@ -84,9 +84,9 @@ start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) * allocate a strip buffer. Use the virtual-array buffer as workspace. */ if (post->buffer == NULL) { - post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - (JDIMENSION) 0, post->strip_height, TRUE); + post->buffer = (*cinfo->mem->access_virt_sarray) + ((j_common_ptr) cinfo, post->whole_image, + (JDIMENSION) 0, post->strip_height, TRUE); } } else { /* For single-pass processing without color quantization, @@ -124,10 +124,10 @@ start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) METHODDEF(void) post_process_1pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION num_rows, max_rows; @@ -139,11 +139,11 @@ post_process_1pass (j_decompress_ptr cinfo, max_rows = post->strip_height; num_rows = 0; (*cinfo->upsample->upsample) (cinfo, - input_buf, in_row_group_ctr, in_row_groups_avail, - post->buffer, &num_rows, max_rows); + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &num_rows, max_rows); /* Quantize and emit data. */ (*cinfo->cquantize->color_quantize) (cinfo, - post->buffer, output_buf + *out_row_ctr, (int) num_rows); + post->buffer, output_buf + *out_row_ctr, (int) num_rows); *out_row_ctr += num_rows; } @@ -156,10 +156,10 @@ post_process_1pass (j_decompress_ptr cinfo, METHODDEF(void) post_process_prepass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION old_next_row, num_rows; @@ -167,22 +167,22 @@ post_process_prepass (j_decompress_ptr cinfo, /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - post->starting_row, post->strip_height, TRUE); + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, TRUE); } /* Upsample some data (up to a strip height's worth). */ old_next_row = post->next_row; (*cinfo->upsample->upsample) (cinfo, - input_buf, in_row_group_ctr, in_row_groups_avail, - post->buffer, &post->next_row, post->strip_height); + input_buf, in_row_group_ctr, in_row_groups_avail, + post->buffer, &post->next_row, post->strip_height); /* Allow quantizer to scan new data. No data is emitted, */ /* but we advance out_row_ctr so outer loop can tell when we're done. */ if (post->next_row > old_next_row) { num_rows = post->next_row - old_next_row; (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, - (JSAMPARRAY) NULL, (int) num_rows); + (JSAMPARRAY) NULL, (int) num_rows); *out_row_ctr += num_rows; } @@ -200,10 +200,10 @@ post_process_prepass (j_decompress_ptr cinfo, METHODDEF(void) post_process_2pass (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION num_rows, max_rows; @@ -211,8 +211,8 @@ post_process_2pass (j_decompress_ptr cinfo, /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { post->buffer = (*cinfo->mem->access_virt_sarray) - ((j_common_ptr) cinfo, post->whole_image, - post->starting_row, post->strip_height, FALSE); + ((j_common_ptr) cinfo, post->whole_image, + post->starting_row, post->strip_height, FALSE); } /* Determine number of rows to emit. */ @@ -227,8 +227,8 @@ post_process_2pass (j_decompress_ptr cinfo, /* Quantize and emit data. */ (*cinfo->cquantize->color_quantize) (cinfo, - post->buffer + post->next_row, output_buf + *out_row_ctr, - (int) num_rows); + post->buffer + post->next_row, output_buf + *out_row_ctr, + (int) num_rows); *out_row_ctr += num_rows; /* Advance if we filled the strip. */ @@ -253,7 +253,7 @@ jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) post = (my_post_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_post_controller)); + SIZEOF(my_post_controller)); cinfo->post = (struct jpeg_d_post_controller *) post; post->pub.start_pass = start_pass_dpost; post->whole_image = NULL; /* flag for no virtual arrays */ @@ -271,20 +271,20 @@ jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) /* We round up the number of rows to a multiple of the strip height. */ #ifdef QUANT_2PASS_SUPPORTED post->whole_image = (*cinfo->mem->request_virt_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, - cinfo->output_width * cinfo->out_color_components, - (JDIMENSION) jround_up((long) cinfo->output_height, - (long) post->strip_height), - post->strip_height); + ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, + cinfo->output_width * cinfo->out_color_components, + (JDIMENSION) jround_up((long) cinfo->output_height, + (long) post->strip_height), + post->strip_height); #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif /* QUANT_2PASS_SUPPORTED */ } else { /* One-pass color quantization: just make a strip buffer. */ post->buffer = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - cinfo->output_width * cinfo->out_color_components, - post->strip_height); + ((j_common_ptr) cinfo, JPOOL_IMAGE, + cinfo->output_width * cinfo->out_color_components, + post->strip_height); } } } diff --git a/3rdparty/libjpeg/jdsample.c b/3rdparty/libjpeg/jdsample.c index 41dc50e1c3..fd9907e20c 100644 --- a/3rdparty/libjpeg/jdsample.c +++ b/3rdparty/libjpeg/jdsample.c @@ -2,7 +2,7 @@ * jdsample.c * * Copyright (C) 1991-1996, Thomas G. Lane. - * Modified 2002-2008 by Guido Vollbeding. + * Modified 2002-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -26,8 +26,8 @@ /* Pointer to routine to upsample a single component */ typedef JMETHOD(void, upsample1_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); /* Private subobject */ @@ -88,10 +88,10 @@ start_pass_upsample (j_decompress_ptr cinfo) METHODDEF(void) sep_upsample (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail) + JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; int ci; @@ -101,13 +101,13 @@ sep_upsample (j_decompress_ptr cinfo, /* Fill the conversion buffer, if it's empty */ if (upsample->next_row_out >= cinfo->max_v_samp_factor) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { + ci++, compptr++) { /* Invoke per-component upsample method. Notice we pass a POINTER * to color_buf[ci], so that fullsize_upsample can change it. */ (*upsample->methods[ci]) (cinfo, compptr, - input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), - upsample->color_buf + ci); + input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), + upsample->color_buf + ci); } upsample->next_row_out = 0; } @@ -119,7 +119,7 @@ sep_upsample (j_decompress_ptr cinfo, /* Not more than the distance to the end of the image. Need this test * in case the image height is not a multiple of max_v_samp_factor: */ - if (num_rows > upsample->rows_to_go) + if (num_rows > upsample->rows_to_go) num_rows = upsample->rows_to_go; /* And not more than what the client can accept: */ out_rows_avail -= *out_row_ctr; @@ -127,9 +127,9 @@ sep_upsample (j_decompress_ptr cinfo, num_rows = out_rows_avail; (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, - (JDIMENSION) upsample->next_row_out, - output_buf + *out_row_ctr, - (int) num_rows); + (JDIMENSION) upsample->next_row_out, + output_buf + *out_row_ctr, + (int) num_rows); /* Adjust counts */ *out_row_ctr += num_rows; @@ -156,7 +156,7 @@ sep_upsample (j_decompress_ptr cinfo, METHODDEF(void) fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { *output_data_ptr = input_data; } @@ -169,7 +169,7 @@ fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, METHODDEF(void) noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { *output_data_ptr = NULL; /* safety check */ } @@ -188,7 +188,7 @@ noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, METHODDEF(void) int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; JSAMPARRAY output_data = *output_data_ptr; @@ -211,13 +211,13 @@ int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, while (outptr < outend) { invalue = *inptr++; /* don't need GETJSAMPLE() here */ for (h = h_expand; h > 0; h--) { - *outptr++ = invalue; + *outptr++ = invalue; } } /* Generate any additional output rows by duplicating the first one */ if (v_expand > 1) { jcopy_sample_rows(output_data, outrow, output_data, outrow+1, - v_expand-1, cinfo->output_width); + v_expand-1, cinfo->output_width); } inrow++; outrow += v_expand; @@ -232,7 +232,7 @@ int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, METHODDEF(void) h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; @@ -260,7 +260,7 @@ h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, METHODDEF(void) h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) + JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; @@ -279,7 +279,7 @@ h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, *outptr++ = invalue; } jcopy_sample_rows(output_data, outrow, output_data, outrow+1, - 1, cinfo->output_width); + 1, cinfo->output_width); inrow++; outrow += 2; } @@ -296,13 +296,12 @@ jinit_upsampler (j_decompress_ptr cinfo) my_upsample_ptr upsample; int ci; jpeg_component_info * compptr; - boolean need_buffer; int h_in_group, v_in_group, h_out_group, v_out_group; upsample = (my_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_upsampler)); - cinfo->upsample = (struct jpeg_upsampler *) upsample; + SIZEOF(my_upsampler)); + cinfo->upsample = &upsample->pub; upsample->pub.start_pass = start_pass_upsample; upsample->pub.upsample = sep_upsample; upsample->pub.need_context_rows = FALSE; /* until we find out differently */ @@ -319,43 +318,41 @@ jinit_upsampler (j_decompress_ptr cinfo) * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. */ h_in_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / - cinfo->min_DCT_h_scaled_size; + cinfo->min_DCT_h_scaled_size; v_in_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / - cinfo->min_DCT_v_scaled_size; + cinfo->min_DCT_v_scaled_size; h_out_group = cinfo->max_h_samp_factor; v_out_group = cinfo->max_v_samp_factor; upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ - need_buffer = TRUE; if (! compptr->component_needed) { /* Don't bother to upsample an uninteresting component. */ upsample->methods[ci] = noop_upsample; - need_buffer = FALSE; - } else if (h_in_group == h_out_group && v_in_group == v_out_group) { + continue; /* don't need to allocate buffer */ + } + if (h_in_group == h_out_group && v_in_group == v_out_group) { /* Fullsize components can be processed without any work. */ upsample->methods[ci] = fullsize_upsample; - need_buffer = FALSE; - } else if (h_in_group * 2 == h_out_group && - v_in_group == v_out_group) { + continue; /* don't need to allocate buffer */ + } + if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) { /* Special case for 2h1v upsampling */ upsample->methods[ci] = h2v1_upsample; } else if (h_in_group * 2 == h_out_group && - v_in_group * 2 == v_out_group) { + v_in_group * 2 == v_out_group) { /* Special case for 2h2v upsampling */ upsample->methods[ci] = h2v2_upsample; } else if ((h_out_group % h_in_group) == 0 && - (v_out_group % v_in_group) == 0) { + (v_out_group % v_in_group) == 0) { /* Generic integral-factors upsampling method */ upsample->methods[ci] = int_upsample; upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); - if (need_buffer) { - upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) - ((j_common_ptr) cinfo, JPOOL_IMAGE, - (JDIMENSION) jround_up((long) cinfo->output_width, - (long) cinfo->max_h_samp_factor), - (JDIMENSION) cinfo->max_v_samp_factor); - } + upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (JDIMENSION) jround_up((long) cinfo->output_width, + (long) cinfo->max_h_samp_factor), + (JDIMENSION) cinfo->max_v_samp_factor); } } diff --git a/3rdparty/libjpeg/jdtrans.c b/3rdparty/libjpeg/jdtrans.c index 863973915e..22dd47fb5c 100644 --- a/3rdparty/libjpeg/jdtrans.c +++ b/3rdparty/libjpeg/jdtrans.c @@ -56,20 +56,20 @@ jpeg_read_coefficients (j_decompress_ptr cinfo) int retcode; /* Call progress monitor hook if present */ if (cinfo->progress != NULL) - (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); + (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); /* Absorb some more input */ retcode = (*cinfo->inputctl->consume_input) (cinfo); if (retcode == JPEG_SUSPENDED) - return NULL; + return NULL; if (retcode == JPEG_REACHED_EOI) - break; + break; /* Advance progress counter if appropriate */ if (cinfo->progress != NULL && - (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { - if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { - /* startup underestimated number of scans; ratchet up one scan */ - cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; - } + (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { + if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { + /* startup underestimated number of scans; ratchet up one scan */ + cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; + } } } /* Set state so that jpeg_finish_decompress does the right thing */ diff --git a/3rdparty/libjpeg/jerror.c b/3rdparty/libjpeg/jerror.c index d1329ed2d9..7163af699c 100644 --- a/3rdparty/libjpeg/jerror.c +++ b/3rdparty/libjpeg/jerror.c @@ -2,7 +2,7 @@ * jerror.c * * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2012 by Guido Vollbeding. + * Modified 2012-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -19,16 +19,16 @@ * These routines are used by both the compression and decompression code. */ +#ifdef USE_WINDOWS_MESSAGEBOX +#include +#endif + /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jversion.h" #include "jerror.h" -#ifdef USE_WINDOWS_MESSAGEBOX -#include -#endif - #ifndef EXIT_FAILURE /* define exit() codes if not provided */ #define EXIT_FAILURE 1 #endif @@ -106,7 +106,7 @@ output_message (j_common_ptr cinfo) #ifdef USE_WINDOWS_MESSAGEBOX /* Display it in a message dialog box */ MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", - MB_OK | MB_ICONERROR); + MB_OK | MB_ICONERROR); #else /* Send it to stderr, adding a newline */ fprintf(stderr, "%s\n", buffer); @@ -168,8 +168,8 @@ format_message (j_common_ptr cinfo, char * buffer) if (msg_code > 0 && msg_code <= err->last_jpeg_message) { msgtext = err->jpeg_message_table[msg_code]; } else if (err->addon_message_table != NULL && - msg_code >= err->first_addon_message && - msg_code <= err->last_addon_message) { + msg_code >= err->first_addon_message && + msg_code <= err->last_addon_message) { msgtext = err->addon_message_table[msg_code - err->first_addon_message]; } @@ -194,10 +194,10 @@ format_message (j_common_ptr cinfo, char * buffer) sprintf(buffer, msgtext, err->msg_parm.s); else sprintf(buffer, msgtext, - err->msg_parm.i[0], err->msg_parm.i[1], - err->msg_parm.i[2], err->msg_parm.i[3], - err->msg_parm.i[4], err->msg_parm.i[5], - err->msg_parm.i[6], err->msg_parm.i[7]); + err->msg_parm.i[0], err->msg_parm.i[1], + err->msg_parm.i[2], err->msg_parm.i[3], + err->msg_parm.i[4], err->msg_parm.i[5], + err->msg_parm.i[6], err->msg_parm.i[7]); } diff --git a/3rdparty/libjpeg/jerror.h b/3rdparty/libjpeg/jerror.h index 5d1db58d85..a4b661f716 100644 --- a/3rdparty/libjpeg/jerror.h +++ b/3rdparty/libjpeg/jerror.h @@ -48,25 +48,25 @@ JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request") JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range") JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported") JMESSAGE(JERR_BAD_DROP_SAMPLING, - "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") + "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c") JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition") JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") JMESSAGE(JERR_BAD_LIB_VERSION, - "Wrong JPEG library version: library is %d, caller expects %d") + "Wrong JPEG library version: library is %d, caller expects %d") JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") JMESSAGE(JERR_BAD_PROGRESSION, - "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") + "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d") JMESSAGE(JERR_BAD_PROG_SCRIPT, - "Invalid progressive parameters at scan script entry %d") + "Invalid progressive parameters at scan script entry %d") JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d") JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") JMESSAGE(JERR_BAD_STRUCT_SIZE, - "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") + "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u") JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small") JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") @@ -90,7 +90,7 @@ JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") JMESSAGE(JERR_MISMATCHED_QUANT_TABLE, - "Cannot transcode due to multiple use of quantization table %d") + "Cannot transcode due to multiple use of quantization table %d") JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data") JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change") JMESSAGE(JERR_NOTIMPL, "Not implemented yet") @@ -103,7 +103,7 @@ JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") JMESSAGE(JERR_QUANT_COMPONENTS, - "Cannot quantize more than %d color components") + "Cannot quantize more than %d color components") JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") JMESSAGE(JERR_SOF_BEFORE, "Invalid JPEG file structure: %s before SOF") @@ -115,7 +115,7 @@ JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") JMESSAGE(JERR_TFILE_WRITE, - "Write failed on temporary file --- out of disk space?") + "Write failed on temporary file --- out of disk space?") JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines") JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x") JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") @@ -125,9 +125,9 @@ JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) JMESSAGE(JMSG_VERSION, JVERSION) JMESSAGE(JTRC_16BIT_TABLES, - "Caution: quantization tables are too coarse for baseline JPEG") + "Caution: quantization tables are too coarse for baseline JPEG") JMESSAGE(JTRC_ADOBE, - "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") + "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") @@ -140,9 +140,9 @@ JMESSAGE(JTRC_EOI, "End Of Image") JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d") JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, - "Warning: thumbnail image size does not match data length %u") + "Warning: thumbnail image size does not match data length %u") JMESSAGE(JTRC_JFIF_EXTENSION, - "JFIF extension marker: type 0x%02x, length %u") + "JFIF extension marker: type 0x%02x, length %u") JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u") JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") @@ -153,7 +153,7 @@ JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") JMESSAGE(JTRC_RST, "RST%d") JMESSAGE(JTRC_SMOOTH_NOTIMPL, - "Smoothing not supported with nonstandard sampling ratios") + "Smoothing not supported with nonstandard sampling ratios") JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") JMESSAGE(JTRC_SOI, "Start of Image") @@ -163,27 +163,27 @@ JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d") JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") JMESSAGE(JTRC_THUMB_JPEG, - "JFIF extension marker: JPEG-compressed thumbnail image, length %u") + "JFIF extension marker: JPEG-compressed thumbnail image, length %u") JMESSAGE(JTRC_THUMB_PALETTE, - "JFIF extension marker: palette thumbnail image, length %u") + "JFIF extension marker: palette thumbnail image, length %u") JMESSAGE(JTRC_THUMB_RGB, - "JFIF extension marker: RGB thumbnail image, length %u") + "JFIF extension marker: RGB thumbnail image, length %u") JMESSAGE(JTRC_UNKNOWN_IDS, - "Unrecognized component IDs %d %d %d, assuming YCbCr") + "Unrecognized component IDs %d %d %d, assuming YCbCr") JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code") JMESSAGE(JWRN_BOGUS_PROGRESSION, - "Inconsistent progression sequence for component %d coefficient %d") + "Inconsistent progression sequence for component %d coefficient %d") JMESSAGE(JWRN_EXTRANEOUS_DATA, - "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") + "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d") JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") JMESSAGE(JWRN_MUST_RESYNC, - "Corrupt JPEG data: found marker 0x%02x instead of RST%d") + "Corrupt JPEG data: found marker 0x%02x instead of RST%d") JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") @@ -276,26 +276,26 @@ JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines") (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - _mp[4] = (p5); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ - _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ - _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ - (cinfo)->err->msg_code = (code); \ - (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMSS(cinfo,lvl,code,str) \ ((cinfo)->err->msg_code = (code), \ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ diff --git a/3rdparty/libjpeg/jfdctflt.c b/3rdparty/libjpeg/jfdctflt.c index 74d0d862dc..0ebc186d22 100644 --- a/3rdparty/libjpeg/jfdctflt.c +++ b/3rdparty/libjpeg/jfdctflt.c @@ -2,7 +2,7 @@ * jfdctflt.c * * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2003-2009 by Guido Vollbeding. + * Modified 2003-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -54,6 +54,8 @@ /* * Perform the forward DCT on one block of samples. + * + * cK represents cos(K*pi/16). */ GLOBAL(void) @@ -89,7 +91,7 @@ jpeg_fdct_float (FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ dataptr[4] = tmp10 - tmp11; diff --git a/3rdparty/libjpeg/jfdctfst.c b/3rdparty/libjpeg/jfdctfst.c index 8cad5f2293..d779f78bf4 100644 --- a/3rdparty/libjpeg/jfdctfst.c +++ b/3rdparty/libjpeg/jfdctfst.c @@ -2,7 +2,7 @@ * jfdctfst.c * * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2003-2009 by Guido Vollbeding. + * Modified 2003-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -109,6 +109,8 @@ /* * Perform the forward DCT on one block of samples. + * + * cK represents cos(K*pi/16). */ GLOBAL(void) @@ -145,7 +147,7 @@ jpeg_fdct_ifast (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ dataptr[4] = tmp10 - tmp11; diff --git a/3rdparty/libjpeg/jfdctint.c b/3rdparty/libjpeg/jfdctint.c index 5077c95e51..7ed42e5db5 100644 --- a/3rdparty/libjpeg/jfdctint.c +++ b/3rdparty/libjpeg/jfdctint.c @@ -2,7 +2,7 @@ * jfdctint.c * * Copyright (C) 1991-1996, Thomas G. Lane. - * Modification developed 2003-2009 by Guido Vollbeding. + * Modification developed 2003-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -165,16 +165,18 @@ jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * cK represents sqrt(2) * cos(K*pi/16). + */ dataptr = data; for (ctr = 0; ctr < DCTSIZE; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + * rotator "c1" should be "c6". */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); @@ -192,51 +194,53 @@ jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS); dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); - dataptr[2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), - CONST_BITS-PASS1_BITS); - dataptr[6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), - CONST_BITS-PASS1_BITS); + + dataptr[2] = (DCTELEM) + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents sqrt(2) * cos(K*pi/16). * i0..i3 in the paper are tmp0..tmp3 here. */ - tmp10 = tmp0 + tmp3; - tmp11 = tmp1 + tmp2; tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; - z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); - tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ - tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ - tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ - tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ - + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; - dataptr[1] = (DCTELEM) - RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS); - dataptr[3] = (DCTELEM) - RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS); - dataptr[5] = (DCTELEM) - RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS); - dataptr[7] = (DCTELEM) - RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS); + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } @@ -244,12 +248,13 @@ jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. + * cK represents sqrt(2) * cos(K*pi/16). */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + * rotator "c1" should be "c6". */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; @@ -271,47 +276,49 @@ jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS); - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS+PASS1_BITS-1); + dataptr[DCTSIZE*2] = (DCTELEM) - RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), CONST_BITS+PASS1_BITS); + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) - RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), CONST_BITS+PASS1_BITS); + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * cK represents sqrt(2) * cos(K*pi/16). * i0..i3 in the paper are tmp0..tmp3 here. */ - tmp10 = tmp0 + tmp3; - tmp11 = tmp1 + tmp2; tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; - z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS+PASS1_BITS-1); - tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ - tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ - tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ - tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ - + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; - dataptr[DCTSIZE*1] = (DCTELEM) - RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*3] = (DCTELEM) - RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*5] = (DCTELEM) - RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*7] = (DCTELEM) - RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS+PASS1_BITS); + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } @@ -338,10 +345,11 @@ jpeg_fdct_7x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* cK represents sqrt(2) * cos(K*pi/14). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * cK represents sqrt(2) * cos(K*pi/14). + */ dataptr = data; for (ctr = 0; ctr < 7; ctr++) { @@ -359,7 +367,7 @@ jpeg_fdct_7x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]); z1 = tmp0 + tmp2; - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS); tmp3 += tmp3; @@ -373,7 +381,7 @@ jpeg_fdct_7x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */ dataptr[4] = (DCTELEM) DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS); /* Odd part */ @@ -419,7 +427,7 @@ jpeg_fdct_7x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) z1 = tmp0 + tmp2; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); tmp3 += tmp3; z1 -= tmp3; z1 -= tmp3; @@ -431,7 +439,7 @@ jpeg_fdct_7x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS); /* Odd part */ @@ -472,10 +480,11 @@ jpeg_fdct_6x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* cK represents sqrt(2) * cos(K*pi/12). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * cK represents sqrt(2) * cos(K*pi/12). + */ dataptr = data; for (ctr = 0; ctr < 6; ctr++) { @@ -494,20 +503,20 @@ jpeg_fdct_6x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS); dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); /* Odd part */ tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS)); dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS); @@ -541,13 +550,13 @@ jpeg_fdct_6x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); /* Odd part */ @@ -555,13 +564,13 @@ jpeg_fdct_6x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } @@ -585,12 +594,13 @@ jpeg_fdct_5x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* We scale the results further by 2 as part of output adaption */ - /* scaling for different DCT size. */ - /* cK represents sqrt(2) * cos(K*pi/10). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * cK represents sqrt(2) * cos(K*pi/10). + */ dataptr = data; for (ctr = 0; ctr < 5; ctr++) { @@ -608,7 +618,7 @@ jpeg_fdct_5x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << (PASS1_BITS+1)); tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */ @@ -623,10 +633,10 @@ jpeg_fdct_5x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */ - CONST_BITS-PASS1_BITS-1); + CONST_BITS-PASS1_BITS-1); dataptr[3] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */ - CONST_BITS-PASS1_BITS-1); + CONST_BITS-PASS1_BITS-1); dataptr += DCTSIZE; /* advance pointer to next row */ } @@ -655,7 +665,7 @@ jpeg_fdct_5x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */ tmp10 -= tmp2 << 2; tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */ @@ -668,10 +678,10 @@ jpeg_fdct_5x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } @@ -695,11 +705,12 @@ jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* We must also scale the output by (8/4)**2 = 2**2, which we add here. */ - /* cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We must also scale the output by (8/4)**2 = 2**2, which we add here. + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. + */ dataptr = data; for (ctr = 0; ctr < 4; ctr++) { @@ -713,7 +724,7 @@ jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+2)); dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+2)); @@ -726,10 +737,10 @@ jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ - CONST_BITS-PASS1_BITS-2); + CONST_BITS-PASS1_BITS-2); dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ - CONST_BITS-PASS1_BITS-2); + CONST_BITS-PASS1_BITS-2); dataptr += DCTSIZE; /* advance pointer to next row */ } @@ -737,6 +748,7 @@ jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ dataptr = data; @@ -761,10 +773,10 @@ jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } @@ -787,12 +799,13 @@ jpeg_fdct_3x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* We scale the results further by 2**2 as part of output adaption */ - /* scaling for different DCT size. */ - /* cK represents sqrt(2) * cos(K*pi/6). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We scale the results further by 2**2 as part of output adaption + * scaling for different DCT size. + * cK represents sqrt(2) * cos(K*pi/6). + */ dataptr = data; for (ctr = 0; ctr < 3; ctr++) { @@ -805,18 +818,18 @@ jpeg_fdct_3x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+2)); dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */ - CONST_BITS-PASS1_BITS-2); + CONST_BITS-PASS1_BITS-2); /* Odd part */ dataptr[1] = (DCTELEM) DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */ - CONST_BITS-PASS1_BITS-2); + CONST_BITS-PASS1_BITS-2); dataptr += DCTSIZE; /* advance pointer to next row */ } @@ -840,16 +853,16 @@ jpeg_fdct_3x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); /* Odd part */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } @@ -863,14 +876,15 @@ jpeg_fdct_3x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) GLOBAL(void) jpeg_fdct_2x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { - INT32 tmp0, tmp1, tmp2, tmp3; + DCTELEM tmp0, tmp1, tmp2, tmp3; JSAMPROW elemptr; /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT. */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + */ /* Row 0 */ elemptr = sample_data[0] + start_col; @@ -890,13 +904,13 @@ jpeg_fdct_2x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) */ /* Column 0 */ - /* Apply unsigned->signed conversion */ - data[DCTSIZE*0] = (DCTELEM) ((tmp0 + tmp2 - 4 * CENTERJSAMPLE) << 4); - data[DCTSIZE*1] = (DCTELEM) ((tmp0 - tmp2) << 4); + /* Apply unsigned->signed conversion. */ + data[DCTSIZE*0] = (tmp0 + tmp2 - 4 * CENTERJSAMPLE) << 4; + data[DCTSIZE*1] = (tmp0 - tmp2) << 4; /* Column 1 */ - data[DCTSIZE*0+1] = (DCTELEM) ((tmp1 + tmp3) << 4); - data[DCTSIZE*1+1] = (DCTELEM) ((tmp1 - tmp3) << 4); + data[DCTSIZE*0+1] = (tmp1 + tmp3) << 4; + data[DCTSIZE*1+1] = (tmp1 - tmp3) << 4; } @@ -907,14 +921,17 @@ jpeg_fdct_2x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) GLOBAL(void) jpeg_fdct_1x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { + DCTELEM dcval; + /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); + dcval = GETJSAMPLE(sample_data[0][start_col]); + /* We leave the result scaled up by an overall factor of 8. */ /* We must also scale the output by (8/1)**2 = 2**6. */ - /* Apply unsigned->signed conversion */ - data[0] = (DCTELEM) - ((GETJSAMPLE(sample_data[0][start_col]) - CENTERJSAMPLE) << 6); + /* Apply unsigned->signed conversion. */ + data[0] = (dcval - CENTERJSAMPLE) << 6; } @@ -935,11 +952,12 @@ jpeg_fdct_9x9 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* we scale the results further by 2 as part of output adaption */ - /* scaling for different DCT size. */ - /* cK represents sqrt(2) * cos(K*pi/18). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * we scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * cK represents sqrt(2) * cos(K*pi/18). + */ dataptr = data; ctr = 0; @@ -961,25 +979,25 @@ jpeg_fdct_9x9 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) z1 = tmp0 + tmp2 + tmp3; z2 = tmp1 + tmp4; - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((z1 + z2 - 9 * CENTERJSAMPLE) << 1); dataptr[6] = (DCTELEM) DESCALE(MULTIPLY(z1 - z2 - z2, FIX(0.707106781)), /* c6 */ - CONST_BITS-1); + CONST_BITS-1); z1 = MULTIPLY(tmp0 - tmp2, FIX(1.328926049)); /* c2 */ z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(0.707106781)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.083350441)) /* c4 */ - + z1 + z2, CONST_BITS-1); + + z1 + z2, CONST_BITS-1); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.245575608)) /* c8 */ - + z1 - z2, CONST_BITS-1); + + z1 - z2, CONST_BITS-1); /* Odd part */ dataptr[3] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.224744871)), /* c3 */ - CONST_BITS-1); + CONST_BITS-1); tmp11 = MULTIPLY(tmp11, FIX(1.224744871)); /* c3 */ tmp0 = MULTIPLY(tmp10 + tmp12, FIX(0.909038955)); /* c5 */ @@ -996,7 +1014,7 @@ jpeg_fdct_9x9 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) if (ctr != DCTSIZE) { if (ctr == 9) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -1029,24 +1047,24 @@ jpeg_fdct_9x9 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) z2 = tmp1 + tmp4; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(z1 + z2, FIX(1.580246914)), /* 128/81 */ - CONST_BITS+2); + CONST_BITS+2); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(MULTIPLY(z1 - z2 - z2, FIX(1.117403309)), /* c6 */ - CONST_BITS+2); + CONST_BITS+2); z1 = MULTIPLY(tmp0 - tmp2, FIX(2.100031287)); /* c2 */ z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(1.117403309)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.711961190)) /* c4 */ - + z1 + z2, CONST_BITS+2); + + z1 + z2, CONST_BITS+2); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.388070096)) /* c8 */ - + z1 - z2, CONST_BITS+2); + + z1 - z2, CONST_BITS+2); /* Odd part */ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.935399303)), /* c3 */ - CONST_BITS+2); + CONST_BITS+2); tmp11 = MULTIPLY(tmp11, FIX(1.935399303)); /* c3 */ tmp0 = MULTIPLY(tmp10 + tmp12, FIX(1.436506004)); /* c5 */ @@ -1084,11 +1102,12 @@ jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* we scale the results further by 2 as part of output adaption */ - /* scaling for different DCT size. */ - /* cK represents sqrt(2) * cos(K*pi/20). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * we scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * cK represents sqrt(2) * cos(K*pi/20). + */ dataptr = data; ctr = 0; @@ -1114,21 +1133,21 @@ jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]); tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << 1); tmp12 += tmp12; dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */ - MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ - CONST_BITS-1); + MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ + CONST_BITS-1); tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */ - CONST_BITS-1); + CONST_BITS-1); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */ - CONST_BITS-1); + CONST_BITS-1); /* Odd part */ @@ -1138,14 +1157,14 @@ jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp2 <<= CONST_BITS; dataptr[1] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */ - MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ - MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ - MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ - CONST_BITS-1); + MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ + CONST_BITS-1); tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */ - MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */ - (tmp11 << (CONST_BITS - 1)) - tmp2; + (tmp11 << (CONST_BITS - 1)) - tmp2; dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-1); dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-1); @@ -1153,7 +1172,7 @@ jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) if (ctr != DCTSIZE) { if (ctr == 10) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -1190,19 +1209,19 @@ jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */ - CONST_BITS+2); + CONST_BITS+2); tmp12 += tmp12; dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */ - MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ - CONST_BITS+2); + MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ + CONST_BITS+2); tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */ - CONST_BITS+2); + CONST_BITS+2); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */ - CONST_BITS+2); + CONST_BITS+2); /* Odd part */ @@ -1210,18 +1229,18 @@ jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp11 = tmp1 - tmp3; dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */ - CONST_BITS+2); + CONST_BITS+2); tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */ - MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ - MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ - MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ - CONST_BITS+2); + MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ + CONST_BITS+2); tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */ - MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */ - MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ + MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+2); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+2); @@ -1248,11 +1267,12 @@ jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* we scale the results further by 2 as part of output adaption */ - /* scaling for different DCT size. */ - /* cK represents sqrt(2) * cos(K*pi/22). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * we scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * cK represents sqrt(2) * cos(K*pi/22). + */ dataptr = data; ctr = 0; @@ -1274,7 +1294,7 @@ jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[7]); tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[6]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 - 11 * CENTERJSAMPLE) << 1); tmp5 += tmp5; @@ -1284,22 +1304,22 @@ jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp3 -= tmp5; tmp4 -= tmp5; z1 = MULTIPLY(tmp0 + tmp3, FIX(1.356927976)) + /* c2 */ - MULTIPLY(tmp2 + tmp4, FIX(0.201263574)); /* c10 */ + MULTIPLY(tmp2 + tmp4, FIX(0.201263574)); /* c10 */ z2 = MULTIPLY(tmp1 - tmp3, FIX(0.926112931)); /* c6 */ z3 = MULTIPLY(tmp0 - tmp1, FIX(1.189712156)); /* c4 */ dataptr[2] = (DCTELEM) DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.018300590)) /* c2+c8-c6 */ - - MULTIPLY(tmp4, FIX(1.390975730)), /* c4+c10 */ - CONST_BITS-1); + - MULTIPLY(tmp4, FIX(1.390975730)), /* c4+c10 */ + CONST_BITS-1); dataptr[4] = (DCTELEM) DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.062335650)) /* c4-c6-c10 */ - - MULTIPLY(tmp2, FIX(1.356927976)) /* c2 */ - + MULTIPLY(tmp4, FIX(0.587485545)), /* c8 */ - CONST_BITS-1); + - MULTIPLY(tmp2, FIX(1.356927976)) /* c2 */ + + MULTIPLY(tmp4, FIX(0.587485545)), /* c8 */ + CONST_BITS-1); dataptr[6] = (DCTELEM) DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.620527200)) /* c2+c4-c6 */ - - MULTIPLY(tmp2, FIX(0.788749120)), /* c8+c10 */ - CONST_BITS-1); + - MULTIPLY(tmp2, FIX(0.788749120)), /* c8+c10 */ + CONST_BITS-1); /* Odd part */ @@ -1307,16 +1327,16 @@ jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.068791298)); /* c5 */ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.764581576)); /* c7 */ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.719967871)) /* c7+c5+c3-c1 */ - + MULTIPLY(tmp14, FIX(0.398430003)); /* c9 */ + + MULTIPLY(tmp14, FIX(0.398430003)); /* c9 */ tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.764581576)); /* -c7 */ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.399818907)); /* -c1 */ tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.276416582)) /* c9+c7+c1-c3 */ - - MULTIPLY(tmp14, FIX(1.068791298)); /* c5 */ + - MULTIPLY(tmp14, FIX(1.068791298)); /* c5 */ tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.398430003)); /* c9 */ tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(1.989053629)) /* c9+c5+c3-c7 */ - + MULTIPLY(tmp14, FIX(1.399818907)); /* c1 */ + + MULTIPLY(tmp14, FIX(1.399818907)); /* c1 */ tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.305598626)) /* c1+c5-c9-c7 */ - - MULTIPLY(tmp14, FIX(1.286413905)); /* c3 */ + - MULTIPLY(tmp14, FIX(1.286413905)); /* c3 */ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-1); dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-1); @@ -1327,7 +1347,7 @@ jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) if (ctr != DCTSIZE) { if (ctr == 11) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -1360,8 +1380,8 @@ jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5, - FIX(1.057851240)), /* 128/121 */ - CONST_BITS+2); + FIX(1.057851240)), /* 128/121 */ + CONST_BITS+2); tmp5 += tmp5; tmp0 -= tmp5; tmp1 -= tmp5; @@ -1369,22 +1389,22 @@ jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp3 -= tmp5; tmp4 -= tmp5; z1 = MULTIPLY(tmp0 + tmp3, FIX(1.435427942)) + /* c2 */ - MULTIPLY(tmp2 + tmp4, FIX(0.212906922)); /* c10 */ + MULTIPLY(tmp2 + tmp4, FIX(0.212906922)); /* c10 */ z2 = MULTIPLY(tmp1 - tmp3, FIX(0.979689713)); /* c6 */ z3 = MULTIPLY(tmp0 - tmp1, FIX(1.258538479)); /* c4 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.077210542)) /* c2+c8-c6 */ - - MULTIPLY(tmp4, FIX(1.471445400)), /* c4+c10 */ - CONST_BITS+2); + - MULTIPLY(tmp4, FIX(1.471445400)), /* c4+c10 */ + CONST_BITS+2); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.065941844)) /* c4-c6-c10 */ - - MULTIPLY(tmp2, FIX(1.435427942)) /* c2 */ - + MULTIPLY(tmp4, FIX(0.621472312)), /* c8 */ - CONST_BITS+2); + - MULTIPLY(tmp2, FIX(1.435427942)) /* c2 */ + + MULTIPLY(tmp4, FIX(0.621472312)), /* c8 */ + CONST_BITS+2); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.714276708)) /* c2+c4-c6 */ - - MULTIPLY(tmp2, FIX(0.834379234)), /* c8+c10 */ - CONST_BITS+2); + - MULTIPLY(tmp2, FIX(0.834379234)), /* c8+c10 */ + CONST_BITS+2); /* Odd part */ @@ -1392,16 +1412,16 @@ jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.130622199)); /* c5 */ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.808813568)); /* c7 */ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.819470145)) /* c7+c5+c3-c1 */ - + MULTIPLY(tmp14, FIX(0.421479672)); /* c9 */ + + MULTIPLY(tmp14, FIX(0.421479672)); /* c9 */ tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.808813568)); /* -c7 */ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.480800167)); /* -c1 */ tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.350258864)) /* c9+c7+c1-c3 */ - - MULTIPLY(tmp14, FIX(1.130622199)); /* c5 */ + - MULTIPLY(tmp14, FIX(1.130622199)); /* c5 */ tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.421479672)); /* c9 */ tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(2.104122847)) /* c9+c5+c3-c7 */ - + MULTIPLY(tmp14, FIX(1.480800167)); /* c1 */ + + MULTIPLY(tmp14, FIX(1.480800167)); /* c1 */ tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.381129125)) /* c1+c5-c9-c7 */ - - MULTIPLY(tmp14, FIX(1.360834544)); /* c3 */ + - MULTIPLY(tmp14, FIX(1.360834544)); /* c3 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2); @@ -1430,9 +1450,10 @@ jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT. */ - /* cK represents sqrt(2) * cos(K*pi/24). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + * cK represents sqrt(2) * cos(K*pi/24). + */ dataptr = data; ctr = 0; @@ -1462,15 +1483,15 @@ jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]); tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) (tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE); dataptr[6] = (DCTELEM) (tmp13 - tmp14 - tmp15); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */ - CONST_BITS); + CONST_BITS); dataptr[2] = (DCTELEM) DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */ - CONST_BITS); + CONST_BITS); /* Odd part */ @@ -1480,14 +1501,14 @@ jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */ - + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ + + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */ - + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ + + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */ - - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ + - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */ - - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ + - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS); @@ -1498,7 +1519,7 @@ jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) if (ctr != DCTSIZE) { if (ctr == 12) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -1539,17 +1560,17 @@ jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */ - CONST_BITS+1); + CONST_BITS+1); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */ - CONST_BITS+1); + CONST_BITS+1); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */ - CONST_BITS+1); + CONST_BITS+1); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */ - MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ - CONST_BITS+1); + MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ + CONST_BITS+1); /* Odd part */ @@ -1559,14 +1580,14 @@ jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */ - + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ + + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */ - + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ + + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */ - - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ + - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */ - - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ + - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+1); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+1); @@ -1596,9 +1617,10 @@ jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT. */ - /* cK represents sqrt(2) * cos(K*pi/26). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + * cK represents sqrt(2) * cos(K*pi/26). + */ dataptr = data; ctr = 0; @@ -1622,7 +1644,7 @@ jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[8]); tmp15 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[7]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) (tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6 - 13 * CENTERJSAMPLE); tmp6 += tmp6; @@ -1634,18 +1656,18 @@ jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp5 -= tmp6; dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.373119086)) + /* c2 */ - MULTIPLY(tmp1, FIX(1.058554052)) + /* c6 */ - MULTIPLY(tmp2, FIX(0.501487041)) - /* c10 */ - MULTIPLY(tmp3, FIX(0.170464608)) - /* c12 */ - MULTIPLY(tmp4, FIX(0.803364869)) - /* c8 */ - MULTIPLY(tmp5, FIX(1.252223920)), /* c4 */ - CONST_BITS); + MULTIPLY(tmp1, FIX(1.058554052)) + /* c6 */ + MULTIPLY(tmp2, FIX(0.501487041)) - /* c10 */ + MULTIPLY(tmp3, FIX(0.170464608)) - /* c12 */ + MULTIPLY(tmp4, FIX(0.803364869)) - /* c8 */ + MULTIPLY(tmp5, FIX(1.252223920)), /* c4 */ + CONST_BITS); z1 = MULTIPLY(tmp0 - tmp2, FIX(1.155388986)) - /* (c4+c6)/2 */ - MULTIPLY(tmp3 - tmp4, FIX(0.435816023)) - /* (c2-c10)/2 */ - MULTIPLY(tmp1 - tmp5, FIX(0.316450131)); /* (c8-c12)/2 */ + MULTIPLY(tmp3 - tmp4, FIX(0.435816023)) - /* (c2-c10)/2 */ + MULTIPLY(tmp1 - tmp5, FIX(0.316450131)); /* (c8-c12)/2 */ z2 = MULTIPLY(tmp0 + tmp2, FIX(0.096834934)) - /* (c4-c6)/2 */ - MULTIPLY(tmp3 + tmp4, FIX(0.937303064)) + /* (c2+c10)/2 */ - MULTIPLY(tmp1 + tmp5, FIX(0.486914739)); /* (c8+c12)/2 */ + MULTIPLY(tmp3 + tmp4, FIX(0.937303064)) + /* (c2+c10)/2 */ + MULTIPLY(tmp1 + tmp5, FIX(0.486914739)); /* (c8+c12)/2 */ dataptr[4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS); dataptr[6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS); @@ -1655,23 +1677,23 @@ jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.322312651)); /* c3 */ tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.163874945)); /* c5 */ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.937797057)) + /* c7 */ - MULTIPLY(tmp14 + tmp15, FIX(0.338443458)); /* c11 */ + MULTIPLY(tmp14 + tmp15, FIX(0.338443458)); /* c11 */ tmp0 = tmp1 + tmp2 + tmp3 - - MULTIPLY(tmp10, FIX(2.020082300)) + /* c3+c5+c7-c1 */ - MULTIPLY(tmp14, FIX(0.318774355)); /* c9-c11 */ + MULTIPLY(tmp10, FIX(2.020082300)) + /* c3+c5+c7-c1 */ + MULTIPLY(tmp14, FIX(0.318774355)); /* c9-c11 */ tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.937797057)) - /* c7 */ - MULTIPLY(tmp11 + tmp12, FIX(0.338443458)); /* c11 */ + MULTIPLY(tmp11 + tmp12, FIX(0.338443458)); /* c11 */ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.163874945)); /* -c5 */ tmp1 += tmp4 + tmp5 + - MULTIPLY(tmp11, FIX(0.837223564)) - /* c5+c9+c11-c3 */ - MULTIPLY(tmp14, FIX(2.341699410)); /* c1+c7 */ + MULTIPLY(tmp11, FIX(0.837223564)) - /* c5+c9+c11-c3 */ + MULTIPLY(tmp14, FIX(2.341699410)); /* c1+c7 */ tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.657217813)); /* -c9 */ tmp2 += tmp4 + tmp6 - - MULTIPLY(tmp12, FIX(1.572116027)) + /* c1+c5-c9-c11 */ - MULTIPLY(tmp15, FIX(2.260109708)); /* c3+c7 */ + MULTIPLY(tmp12, FIX(1.572116027)) + /* c1+c5-c9-c11 */ + MULTIPLY(tmp15, FIX(2.260109708)); /* c3+c7 */ tmp3 += tmp5 + tmp6 + - MULTIPLY(tmp13, FIX(2.205608352)) - /* c3+c5+c9-c7 */ - MULTIPLY(tmp15, FIX(1.742345811)); /* c1+c11 */ + MULTIPLY(tmp13, FIX(2.205608352)) - /* c3+c5+c9-c7 */ + MULTIPLY(tmp15, FIX(1.742345811)); /* c1+c11 */ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS); @@ -1682,7 +1704,7 @@ jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) if (ctr != DCTSIZE) { if (ctr == 13) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -1717,8 +1739,8 @@ jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6, - FIX(0.757396450)), /* 128/169 */ - CONST_BITS+1); + FIX(0.757396450)), /* 128/169 */ + CONST_BITS+1); tmp6 += tmp6; tmp0 -= tmp6; tmp1 -= tmp6; @@ -1728,18 +1750,18 @@ jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp5 -= tmp6; dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.039995521)) + /* c2 */ - MULTIPLY(tmp1, FIX(0.801745081)) + /* c6 */ - MULTIPLY(tmp2, FIX(0.379824504)) - /* c10 */ - MULTIPLY(tmp3, FIX(0.129109289)) - /* c12 */ - MULTIPLY(tmp4, FIX(0.608465700)) - /* c8 */ - MULTIPLY(tmp5, FIX(0.948429952)), /* c4 */ - CONST_BITS+1); + MULTIPLY(tmp1, FIX(0.801745081)) + /* c6 */ + MULTIPLY(tmp2, FIX(0.379824504)) - /* c10 */ + MULTIPLY(tmp3, FIX(0.129109289)) - /* c12 */ + MULTIPLY(tmp4, FIX(0.608465700)) - /* c8 */ + MULTIPLY(tmp5, FIX(0.948429952)), /* c4 */ + CONST_BITS+1); z1 = MULTIPLY(tmp0 - tmp2, FIX(0.875087516)) - /* (c4+c6)/2 */ - MULTIPLY(tmp3 - tmp4, FIX(0.330085509)) - /* (c2-c10)/2 */ - MULTIPLY(tmp1 - tmp5, FIX(0.239678205)); /* (c8-c12)/2 */ + MULTIPLY(tmp3 - tmp4, FIX(0.330085509)) - /* (c2-c10)/2 */ + MULTIPLY(tmp1 - tmp5, FIX(0.239678205)); /* (c8-c12)/2 */ z2 = MULTIPLY(tmp0 + tmp2, FIX(0.073342435)) - /* (c4-c6)/2 */ - MULTIPLY(tmp3 + tmp4, FIX(0.709910013)) + /* (c2+c10)/2 */ - MULTIPLY(tmp1 + tmp5, FIX(0.368787494)); /* (c8+c12)/2 */ + MULTIPLY(tmp3 + tmp4, FIX(0.709910013)) + /* (c2+c10)/2 */ + MULTIPLY(tmp1 + tmp5, FIX(0.368787494)); /* (c8+c12)/2 */ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+1); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS+1); @@ -1749,23 +1771,23 @@ jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.001514908)); /* c3 */ tmp2 = MULTIPLY(tmp10 + tmp12, FIX(0.881514751)); /* c5 */ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.710284161)) + /* c7 */ - MULTIPLY(tmp14 + tmp15, FIX(0.256335874)); /* c11 */ + MULTIPLY(tmp14 + tmp15, FIX(0.256335874)); /* c11 */ tmp0 = tmp1 + tmp2 + tmp3 - - MULTIPLY(tmp10, FIX(1.530003162)) + /* c3+c5+c7-c1 */ - MULTIPLY(tmp14, FIX(0.241438564)); /* c9-c11 */ + MULTIPLY(tmp10, FIX(1.530003162)) + /* c3+c5+c7-c1 */ + MULTIPLY(tmp14, FIX(0.241438564)); /* c9-c11 */ tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.710284161)) - /* c7 */ - MULTIPLY(tmp11 + tmp12, FIX(0.256335874)); /* c11 */ + MULTIPLY(tmp11 + tmp12, FIX(0.256335874)); /* c11 */ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(0.881514751)); /* -c5 */ tmp1 += tmp4 + tmp5 + - MULTIPLY(tmp11, FIX(0.634110155)) - /* c5+c9+c11-c3 */ - MULTIPLY(tmp14, FIX(1.773594819)); /* c1+c7 */ + MULTIPLY(tmp11, FIX(0.634110155)) - /* c5+c9+c11-c3 */ + MULTIPLY(tmp14, FIX(1.773594819)); /* c1+c7 */ tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.497774438)); /* -c9 */ tmp2 += tmp4 + tmp6 - - MULTIPLY(tmp12, FIX(1.190715098)) + /* c1+c5-c9-c11 */ - MULTIPLY(tmp15, FIX(1.711799069)); /* c3+c7 */ + MULTIPLY(tmp12, FIX(1.190715098)) + /* c1+c5-c9-c11 */ + MULTIPLY(tmp15, FIX(1.711799069)); /* c3+c7 */ tmp3 += tmp5 + tmp6 + - MULTIPLY(tmp13, FIX(1.670519935)) - /* c3+c5+c9-c7 */ - MULTIPLY(tmp15, FIX(1.319646532)); /* c1+c11 */ + MULTIPLY(tmp13, FIX(1.670519935)) - /* c3+c5+c9-c7 */ + MULTIPLY(tmp15, FIX(1.319646532)); /* c1+c11 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+1); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+1); @@ -1794,9 +1816,10 @@ jpeg_fdct_14x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT. */ - /* cK represents sqrt(2) * cos(K*pi/28). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + * cK represents sqrt(2) * cos(K*pi/28). + */ dataptr = data; ctr = 0; @@ -1828,26 +1851,26 @@ jpeg_fdct_14x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]); tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) (tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE); tmp13 += tmp13; dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */ - MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ - MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ - CONST_BITS); + MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ + CONST_BITS); tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */ - + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ - CONST_BITS); + + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ + CONST_BITS); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */ - - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ - CONST_BITS); + - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ + CONST_BITS); /* Odd part */ @@ -1859,27 +1882,27 @@ jpeg_fdct_14x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */ tmp10 += tmp11 - tmp3; tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */ - MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ + MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ dataptr[5] = (DCTELEM) DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */ - + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ - CONST_BITS); + + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ + CONST_BITS); tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */ - MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ + MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ dataptr[3] = (DCTELEM) DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */ - - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ - CONST_BITS); + - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ + CONST_BITS); dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp12 + tmp3 + tmp6 - - MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ - CONST_BITS); + MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ + CONST_BITS); ctr++; if (ctr != DCTSIZE) { if (ctr == 14) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -1922,25 +1945,25 @@ jpeg_fdct_14x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13, - FIX(0.653061224)), /* 32/49 */ - CONST_BITS+1); + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+1); tmp13 += tmp13; dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */ - MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ - MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ - CONST_BITS+1); + MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ + CONST_BITS+1); tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */ - + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ - CONST_BITS+1); + + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ + CONST_BITS+1); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */ - - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ - CONST_BITS+1); + - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ + CONST_BITS+1); /* Odd part */ @@ -1948,29 +1971,29 @@ jpeg_fdct_14x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp11 = tmp5 - tmp4; dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6, - FIX(0.653061224)), /* 32/49 */ - CONST_BITS+1); + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+1); tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */ tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */ tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */ tmp10 += tmp11 - tmp3; tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */ - MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ + MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */ - + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ - CONST_BITS+1); + + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ + CONST_BITS+1); tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */ - MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ + MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */ - - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ - CONST_BITS+1); + - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ + CONST_BITS+1); dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp12 + tmp3 - - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ - - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ - CONST_BITS+1); + - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ + - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ + CONST_BITS+1); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ @@ -1995,9 +2018,10 @@ jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT. */ - /* cK represents sqrt(2) * cos(K*pi/30). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + * cK represents sqrt(2) * cos(K*pi/30). + */ dataptr = data; ctr = 0; @@ -2026,21 +2050,21 @@ jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) z1 = tmp0 + tmp4 + tmp5; z2 = tmp1 + tmp3 + tmp6; z3 = tmp2 + tmp7; - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) (z1 + z2 + z3 - 15 * CENTERJSAMPLE); z3 += z3; dataptr[6] = (DCTELEM) DESCALE(MULTIPLY(z1 - z3, FIX(1.144122806)) - /* c6 */ - MULTIPLY(z2 - z3, FIX(0.437016024)), /* c12 */ - CONST_BITS); + MULTIPLY(z2 - z3, FIX(0.437016024)), /* c12 */ + CONST_BITS); tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7; z1 = MULTIPLY(tmp3 - tmp2, FIX(1.531135173)) - /* c2+c14 */ MULTIPLY(tmp6 - tmp2, FIX(2.238241955)); /* c4+c8 */ z2 = MULTIPLY(tmp5 - tmp2, FIX(0.798468008)) - /* c8-c14 */ - MULTIPLY(tmp0 - tmp2, FIX(0.091361227)); /* c2-c4 */ + MULTIPLY(tmp0 - tmp2, FIX(0.091361227)); /* c2-c4 */ z3 = MULTIPLY(tmp0 - tmp3, FIX(1.383309603)) + /* c2 */ - MULTIPLY(tmp6 - tmp5, FIX(0.946293579)) + /* c8 */ - MULTIPLY(tmp1 - tmp4, FIX(0.790569415)); /* (c6+c12)/2 */ + MULTIPLY(tmp6 - tmp5, FIX(0.946293579)) + /* c8 */ + MULTIPLY(tmp1 - tmp4, FIX(0.790569415)); /* (c6+c12)/2 */ dataptr[2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS); dataptr[4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS); @@ -2048,19 +2072,19 @@ jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Odd part */ tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16, - FIX(1.224744871)); /* c5 */ + FIX(1.224744871)); /* c5 */ tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.344997024)) + /* c3 */ - MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.831253876)); /* c9 */ + MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.831253876)); /* c9 */ tmp12 = MULTIPLY(tmp12, FIX(1.224744871)); /* c5 */ tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.406466353)) + /* c1 */ - MULTIPLY(tmp11 + tmp14, FIX(1.344997024)) + /* c3 */ - MULTIPLY(tmp13 + tmp15, FIX(0.575212477)); /* c11 */ + MULTIPLY(tmp11 + tmp14, FIX(1.344997024)) + /* c3 */ + MULTIPLY(tmp13 + tmp15, FIX(0.575212477)); /* c11 */ tmp0 = MULTIPLY(tmp13, FIX(0.475753014)) - /* c7-c11 */ - MULTIPLY(tmp14, FIX(0.513743148)) + /* c3-c9 */ - MULTIPLY(tmp16, FIX(1.700497885)) + tmp4 + tmp12; /* c1+c13 */ + MULTIPLY(tmp14, FIX(0.513743148)) + /* c3-c9 */ + MULTIPLY(tmp16, FIX(1.700497885)) + tmp4 + tmp12; /* c1+c13 */ tmp3 = MULTIPLY(tmp10, - FIX(0.355500862)) - /* -(c1-c7) */ - MULTIPLY(tmp11, FIX(2.176250899)) - /* c3+c9 */ - MULTIPLY(tmp15, FIX(0.869244010)) + tmp4 - tmp12; /* c11+c13 */ + MULTIPLY(tmp11, FIX(2.176250899)) - /* c3+c9 */ + MULTIPLY(tmp15, FIX(0.869244010)) + tmp4 - tmp12; /* c11+c13 */ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS); @@ -2071,7 +2095,7 @@ jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) if (ctr != DCTSIZE) { if (ctr == 15) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -2111,20 +2135,20 @@ jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) z3 = tmp2 + tmp7; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(z1 + z2 + z3, FIX(1.137777778)), /* 256/225 */ - CONST_BITS+2); + CONST_BITS+2); z3 += z3; dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(MULTIPLY(z1 - z3, FIX(1.301757503)) - /* c6 */ - MULTIPLY(z2 - z3, FIX(0.497227121)), /* c12 */ - CONST_BITS+2); + MULTIPLY(z2 - z3, FIX(0.497227121)), /* c12 */ + CONST_BITS+2); tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7; z1 = MULTIPLY(tmp3 - tmp2, FIX(1.742091575)) - /* c2+c14 */ MULTIPLY(tmp6 - tmp2, FIX(2.546621957)); /* c4+c8 */ z2 = MULTIPLY(tmp5 - tmp2, FIX(0.908479156)) - /* c8-c14 */ - MULTIPLY(tmp0 - tmp2, FIX(0.103948774)); /* c2-c4 */ + MULTIPLY(tmp0 - tmp2, FIX(0.103948774)); /* c2-c4 */ z3 = MULTIPLY(tmp0 - tmp3, FIX(1.573898926)) + /* c2 */ - MULTIPLY(tmp6 - tmp5, FIX(1.076671805)) + /* c8 */ - MULTIPLY(tmp1 - tmp4, FIX(0.899492312)); /* (c6+c12)/2 */ + MULTIPLY(tmp6 - tmp5, FIX(1.076671805)) + /* c8 */ + MULTIPLY(tmp1 - tmp4, FIX(0.899492312)); /* (c6+c12)/2 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS+2); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS+2); @@ -2132,19 +2156,19 @@ jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Odd part */ tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16, - FIX(1.393487498)); /* c5 */ + FIX(1.393487498)); /* c5 */ tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.530307725)) + /* c3 */ - MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.945782187)); /* c9 */ + MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.945782187)); /* c9 */ tmp12 = MULTIPLY(tmp12, FIX(1.393487498)); /* c5 */ tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.600246161)) + /* c1 */ - MULTIPLY(tmp11 + tmp14, FIX(1.530307725)) + /* c3 */ - MULTIPLY(tmp13 + tmp15, FIX(0.654463974)); /* c11 */ + MULTIPLY(tmp11 + tmp14, FIX(1.530307725)) + /* c3 */ + MULTIPLY(tmp13 + tmp15, FIX(0.654463974)); /* c11 */ tmp0 = MULTIPLY(tmp13, FIX(0.541301207)) - /* c7-c11 */ - MULTIPLY(tmp14, FIX(0.584525538)) + /* c3-c9 */ - MULTIPLY(tmp16, FIX(1.934788705)) + tmp4 + tmp12; /* c1+c13 */ + MULTIPLY(tmp14, FIX(0.584525538)) + /* c3-c9 */ + MULTIPLY(tmp16, FIX(1.934788705)) + tmp4 + tmp12; /* c1+c13 */ tmp3 = MULTIPLY(tmp10, - FIX(0.404480980)) - /* -(c1-c7) */ - MULTIPLY(tmp11, FIX(2.476089912)) - /* c3+c9 */ - MULTIPLY(tmp15, FIX(0.989006518)) + tmp4 - tmp12; /* c11+c13 */ + MULTIPLY(tmp11, FIX(2.476089912)) - /* c3+c9 */ + MULTIPLY(tmp15, FIX(0.989006518)) + tmp4 - tmp12; /* c11+c13 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2); @@ -2173,10 +2197,11 @@ jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* cK represents sqrt(2) * cos(K*pi/32). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * cK represents sqrt(2) * cos(K*pi/32). + */ dataptr = data; ctr = 0; @@ -2212,49 +2237,49 @@ jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]); tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ - MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ - CONST_BITS-PASS1_BITS); + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS-PASS1_BITS); tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ - MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ - + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ - CONST_BITS-PASS1_BITS); + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ - - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ - CONST_BITS-PASS1_BITS); + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS-PASS1_BITS); /* Odd part */ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ - MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ - MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ - MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ - MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ - MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ - MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ - MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ - - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ - + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ - + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); @@ -2265,7 +2290,7 @@ jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) if (ctr != DCTSIZE) { if (ctr == DCTSIZE * 2) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -2275,6 +2300,7 @@ jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by (8/16)**2 = 1/2**2. + * cK represents sqrt(2) * cos(K*pi/32). */ dataptr = data; @@ -2313,44 +2339,44 @@ jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+2); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ - MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ - CONST_BITS+PASS1_BITS+2); + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS+PASS1_BITS+2); tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ - MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ - + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+10 */ - CONST_BITS+PASS1_BITS+2); + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+10 */ + CONST_BITS+PASS1_BITS+2); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ - - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ - CONST_BITS+PASS1_BITS+2); + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS+PASS1_BITS+2); /* Odd part */ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ - MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ - MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ - MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ - MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ - MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ - MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ - MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ - - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ - + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ - + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+2); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+2); @@ -2380,10 +2406,11 @@ jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32). + */ dataptr = data; ctr = 0; @@ -2419,49 +2446,49 @@ jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]); tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ - MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ - CONST_BITS-PASS1_BITS); + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS-PASS1_BITS); tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ - MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ - + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ - CONST_BITS-PASS1_BITS); + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ - - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ - CONST_BITS-PASS1_BITS); + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS-PASS1_BITS); /* Odd part */ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ - MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ - MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ - MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ - MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ - MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ - MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ - MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ - - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ - + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ - + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); @@ -2475,12 +2502,13 @@ jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. * We must also scale the output by 8/16 = 1/2. + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + * rotator "c1" should be "c6". */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; @@ -2501,43 +2529,43 @@ jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS+1); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS+1); - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), - CONST_BITS+PASS1_BITS+1); - dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), - CONST_BITS+PASS1_BITS+1); + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ + dataptr[DCTSIZE*2] = (DCTELEM) + DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*6] = (DCTELEM) + DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS+1); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). * i0..i3 in the paper are tmp0..tmp3 here. */ - tmp10 = tmp0 + tmp3; - tmp11 = tmp1 + tmp2; tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; - z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ - - tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ - tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ - tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ - tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; - dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0 + tmp10 + tmp12, - CONST_BITS+PASS1_BITS+1); - dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1 + tmp11 + tmp13, - CONST_BITS+PASS1_BITS+1); - dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2 + tmp11 + tmp12, - CONST_BITS+PASS1_BITS+1); - dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3 + tmp10 + tmp13, - CONST_BITS+PASS1_BITS+1); + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS+1); + dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+PASS1_BITS+1); dataptr++; /* advance pointer to next column */ } @@ -2564,10 +2592,11 @@ jpeg_fdct_14x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Zero bottom row of output coefficient block. */ MEMZERO(&data[DCTSIZE*7], SIZEOF(DCTELEM) * DCTSIZE); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28). + */ dataptr = data; for (ctr = 0; ctr < 7; ctr++) { @@ -2598,26 +2627,26 @@ jpeg_fdct_14x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]); tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE) << PASS1_BITS); tmp13 += tmp13; dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */ - MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ - MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ - CONST_BITS-PASS1_BITS); + MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */ + CONST_BITS-PASS1_BITS); tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */ - + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ - CONST_BITS-PASS1_BITS); + + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */ + CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */ - - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ - CONST_BITS-PASS1_BITS); + - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */ + CONST_BITS-PASS1_BITS); /* Odd part */ @@ -2629,21 +2658,21 @@ jpeg_fdct_14x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */ tmp10 += tmp11 - tmp3; tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */ - MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ + MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */ dataptr[5] = (DCTELEM) DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */ - + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ - CONST_BITS-PASS1_BITS); + + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */ + CONST_BITS-PASS1_BITS); tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */ - MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ + MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */ dataptr[3] = (DCTELEM) DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */ - - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ - CONST_BITS-PASS1_BITS); + - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */ + CONST_BITS-PASS1_BITS); dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp12 + tmp3 + tmp6 - - MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ - CONST_BITS-PASS1_BITS); + MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */ + CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } @@ -2672,7 +2701,7 @@ jpeg_fdct_14x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) z1 = tmp0 + tmp2; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */ - CONST_BITS+PASS1_BITS+1); + CONST_BITS+PASS1_BITS+1); tmp3 += tmp3; z1 -= tmp3; z1 -= tmp3; @@ -2684,7 +2713,7 @@ jpeg_fdct_14x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */ - CONST_BITS+PASS1_BITS+1); + CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS+1); /* Odd part */ @@ -2727,10 +2756,11 @@ jpeg_fdct_12x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Zero 2 bottom rows of output coefficient block. */ MEMZERO(&data[DCTSIZE*6], SIZEOF(DCTELEM) * DCTSIZE * 2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24). + */ dataptr = data; for (ctr = 0; ctr < 6; ctr++) { @@ -2759,16 +2789,16 @@ jpeg_fdct_12x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]); tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE) << PASS1_BITS); dataptr[6] = (DCTELEM) ((tmp13 - tmp14 - tmp15) << PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); dataptr[2] = (DCTELEM) DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); /* Odd part */ @@ -2778,14 +2808,14 @@ jpeg_fdct_12x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */ - + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ + + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */ - + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ + + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */ - - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ + - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */ - - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ + - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS); @@ -2820,13 +2850,13 @@ jpeg_fdct_12x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS+1); + CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ - CONST_BITS+PASS1_BITS+1); + CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ - CONST_BITS+PASS1_BITS+1); + CONST_BITS+PASS1_BITS+1); /* Odd part */ @@ -2834,13 +2864,13 @@ jpeg_fdct_12x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS+1); + CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS+1); + CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS+1); + CONST_BITS+PASS1_BITS+1); dataptr++; /* advance pointer to next column */ } @@ -2866,10 +2896,11 @@ jpeg_fdct_10x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Zero 3 bottom rows of output coefficient block. */ MEMZERO(&data[DCTSIZE*5], SIZEOF(DCTELEM) * DCTSIZE * 3); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20). + */ dataptr = data; for (ctr = 0; ctr < 5; ctr++) { @@ -2894,21 +2925,21 @@ jpeg_fdct_10x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]); tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << PASS1_BITS); tmp12 += tmp12; dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */ - MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ - CONST_BITS-PASS1_BITS); + MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */ + CONST_BITS-PASS1_BITS); tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */ dataptr[2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); /* Odd part */ @@ -2918,14 +2949,14 @@ jpeg_fdct_10x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp2 <<= CONST_BITS; dataptr[1] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */ - MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ - MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ - MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ - CONST_BITS-PASS1_BITS); + MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */ + CONST_BITS-PASS1_BITS); tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */ - MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */ - (tmp11 << (CONST_BITS - 1)) - tmp2; + (tmp11 << (CONST_BITS - 1)) - tmp2; dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-PASS1_BITS); dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-PASS1_BITS); @@ -2956,7 +2987,7 @@ jpeg_fdct_10x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */ tmp10 -= tmp2 << 2; tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */ @@ -2969,10 +3000,10 @@ jpeg_fdct_10x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } @@ -2999,17 +3030,19 @@ jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Zero 4 bottom rows of output coefficient block. */ MEMZERO(&data[DCTSIZE*4], SIZEOF(DCTELEM) * DCTSIZE * 4); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* We must also scale the output by 8/4 = 2, which we add here. */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We must also scale the output by 8/4 = 2, which we add here. + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ dataptr = data; for (ctr = 0; ctr < 4; ctr++) { elemptr = sample_data[ctr] + start_col; /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + * rotator "c1" should be "c6". */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); @@ -3027,52 +3060,54 @@ jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << (PASS1_BITS+1)); dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << (PASS1_BITS+1)); - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-2); - dataptr[2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), - CONST_BITS-PASS1_BITS-1); - dataptr[6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), - CONST_BITS-PASS1_BITS-1); + + dataptr[2] = (DCTELEM) + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS-1); + dataptr[6] = (DCTELEM) + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS-1); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). * i0..i3 in the paper are tmp0..tmp3 here. */ - tmp10 = tmp0 + tmp3; - tmp11 = tmp1 + tmp2; tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; - z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-2); - tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ - tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ - tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ - tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ - + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; - dataptr[1] = (DCTELEM) - RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS-1); - dataptr[3] = (DCTELEM) - RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS-1); - dataptr[5] = (DCTELEM) - RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS-1); - dataptr[7] = (DCTELEM) - RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS-1); + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS-PASS1_BITS-1); + dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS-PASS1_BITS-1); + dataptr[5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS-1); + dataptr[7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS-PASS1_BITS-1); dataptr += DCTSIZE; /* advance pointer to next row */ } @@ -3080,7 +3115,8 @@ jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. - * 4-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + * 4-point FDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ dataptr = data; @@ -3099,16 +3135,16 @@ jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Odd part */ - tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ + tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ tmp0 += ONE << (CONST_BITS+PASS1_BITS-1); dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } @@ -3134,12 +3170,13 @@ jpeg_fdct_6x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* We scale the results further by 2 as part of output adaption */ - /* scaling for different DCT size. */ - /* 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ dataptr = data; for (ctr = 0; ctr < 3; ctr++) { @@ -3158,20 +3195,20 @@ jpeg_fdct_6x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << (PASS1_BITS+1)); dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ - CONST_BITS-PASS1_BITS-1); + CONST_BITS-PASS1_BITS-1); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ - CONST_BITS-PASS1_BITS-1); + CONST_BITS-PASS1_BITS-1); /* Odd part */ tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ - CONST_BITS-PASS1_BITS-1); + CONST_BITS-PASS1_BITS-1); dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << (PASS1_BITS+1))); dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << (PASS1_BITS+1)); @@ -3199,16 +3236,16 @@ jpeg_fdct_6x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); /* Odd part */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } @@ -3234,12 +3271,13 @@ jpeg_fdct_4x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* We must also scale the output by (8/4)*(8/2) = 2**3, which we add here. */ - /* 4-point FDCT kernel, */ - /* cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We must also scale the output by (8/4)*(8/2) = 2**3, which we add here. + * 4-point FDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. + */ dataptr = data; for (ctr = 0; ctr < 2; ctr++) { @@ -3253,7 +3291,7 @@ jpeg_fdct_4x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+3)); dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+3)); @@ -3266,10 +3304,10 @@ jpeg_fdct_4x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ - CONST_BITS-PASS1_BITS-3); + CONST_BITS-PASS1_BITS-3); dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ - CONST_BITS-PASS1_BITS-3); + CONST_BITS-PASS1_BITS-3); dataptr += DCTSIZE; /* advance pointer to next row */ } @@ -3307,7 +3345,7 @@ jpeg_fdct_4x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) GLOBAL(void) jpeg_fdct_2x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { - INT32 tmp0, tmp1; + DCTELEM tmp0, tmp1; JSAMPROW elemptr; /* Pre-zero output coefficient block. */ @@ -3323,11 +3361,13 @@ jpeg_fdct_2x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) */ /* Even part */ - /* Apply unsigned->signed conversion */ - data[0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5); + + /* Apply unsigned->signed conversion. */ + data[0] = (tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5; /* Odd part */ - data[1] = (DCTELEM) ((tmp0 - tmp1) << 5); + + data[1] = (tmp0 - tmp1) << 5; } @@ -3350,9 +3390,11 @@ jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) int ctr; SHIFT_TEMPS - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ dataptr = data; ctr = 0; @@ -3360,7 +3402,7 @@ jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) elemptr = sample_data[ctr] + start_col; /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + * rotator "c1" should be "c6". */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); @@ -3378,49 +3420,53 @@ jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS); dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); - dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), - CONST_BITS-PASS1_BITS); - dataptr[6] = (DCTELEM) DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), - CONST_BITS-PASS1_BITS); + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ + dataptr[2] = (DCTELEM) + DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS-PASS1_BITS); + dataptr[6] = (DCTELEM) + DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS-PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). * i0..i3 in the paper are tmp0..tmp3 here. */ - tmp10 = tmp0 + tmp3; - tmp11 = tmp1 + tmp2; tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; - z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ - - tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ - tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ - tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ - tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; - dataptr[1] = (DCTELEM) DESCALE(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS); - dataptr[3] = (DCTELEM) DESCALE(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS); - dataptr[5] = (DCTELEM) DESCALE(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS); - dataptr[7] = (DCTELEM) DESCALE(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS); + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS); + dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS); + dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS); + dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS-PASS1_BITS); ctr++; if (ctr != DCTSIZE) { if (ctr == DCTSIZE * 2) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -3469,44 +3515,44 @@ jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+1); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */ - MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ - CONST_BITS+PASS1_BITS+1); + MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */ + CONST_BITS+PASS1_BITS+1); tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */ - MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ + MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */ - + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ - CONST_BITS+PASS1_BITS+1); + + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */ + CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */ - - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ - CONST_BITS+PASS1_BITS+1); + - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */ + CONST_BITS+PASS1_BITS+1); /* Odd part */ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */ - MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ + MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */ - MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ + MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */ - MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ + MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */ - MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ + MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */ - MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ + MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */ - MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ + MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */ tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ - MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ + MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */ + MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */ - - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ + - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */ - + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ + + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */ - + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ + + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+1); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+1); @@ -3541,10 +3587,11 @@ jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14). + */ dataptr = data; ctr = 0; @@ -3563,7 +3610,7 @@ jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]); z1 = tmp0 + tmp2; - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS); tmp3 += tmp3; @@ -3577,7 +3624,7 @@ jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */ dataptr[4] = (DCTELEM) DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS); /* Odd part */ @@ -3600,7 +3647,7 @@ jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) if (ctr != DCTSIZE) { if (ctr == 14) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -3644,25 +3691,25 @@ jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13, - FIX(0.653061224)), /* 32/49 */ - CONST_BITS+PASS1_BITS); + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+PASS1_BITS); tmp13 += tmp13; dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */ - MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ - MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ - CONST_BITS+PASS1_BITS); + MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */ + MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */ + CONST_BITS+PASS1_BITS); tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */ - + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ - CONST_BITS+PASS1_BITS); + + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */ + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */ - - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ - CONST_BITS+PASS1_BITS); + - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */ + CONST_BITS+PASS1_BITS); /* Odd part */ @@ -3670,29 +3717,29 @@ jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp11 = tmp5 - tmp4; dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6, - FIX(0.653061224)), /* 32/49 */ - CONST_BITS+PASS1_BITS); + FIX(0.653061224)), /* 32/49 */ + CONST_BITS+PASS1_BITS); tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */ tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */ tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */ tmp10 += tmp11 - tmp3; tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */ - MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ + MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */ - + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ - CONST_BITS+PASS1_BITS); + + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */ + CONST_BITS+PASS1_BITS); tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */ - MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ + MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */ - - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ - CONST_BITS+PASS1_BITS); + - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */ + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp11 + tmp12 + tmp3 - - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ - - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ - CONST_BITS+PASS1_BITS); + - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */ + - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */ + CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ wsptr++; /* advance pointer to next column */ @@ -3721,10 +3768,11 @@ jpeg_fdct_6x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). + */ dataptr = data; ctr = 0; @@ -3744,20 +3792,20 @@ jpeg_fdct_6x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]); tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS); dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); dataptr[4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); /* Odd part */ tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS)); dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS); @@ -3767,7 +3815,7 @@ jpeg_fdct_6x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) if (ctr != DCTSIZE) { if (ctr == 12) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -3809,17 +3857,17 @@ jpeg_fdct_6x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */ - MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ - CONST_BITS+PASS1_BITS); + MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */ + CONST_BITS+PASS1_BITS); /* Odd part */ @@ -3829,14 +3877,14 @@ jpeg_fdct_6x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */ - + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ + + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */ - + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ + + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */ - - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ + - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */ - - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ + - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS); @@ -3870,10 +3918,11 @@ jpeg_fdct_5x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10). + */ dataptr = data; ctr = 0; @@ -3892,7 +3941,7 @@ jpeg_fdct_5x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]); tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << PASS1_BITS); tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */ @@ -3907,16 +3956,16 @@ jpeg_fdct_5x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); ctr++; if (ctr != DCTSIZE) { if (ctr == 10) - break; /* Done. */ + break; /* Done. */ dataptr += DCTSIZE; /* advance pointer to next row */ } else dataptr = workspace; /* switch pointer to extended workspace */ @@ -3954,19 +4003,19 @@ jpeg_fdct_5x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); tmp12 += tmp12; dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */ - MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ - CONST_BITS+PASS1_BITS); + MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */ + CONST_BITS+PASS1_BITS); tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); /* Odd part */ @@ -3974,18 +4023,18 @@ jpeg_fdct_5x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp11 = tmp1 - tmp3; dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */ - MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ - MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ - MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ - CONST_BITS+PASS1_BITS); + MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */ + MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */ + MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */ + CONST_BITS+PASS1_BITS); tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */ - MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ + MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */ - MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ + MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+PASS1_BITS); @@ -4015,11 +4064,13 @@ jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* We must also scale the output by 8/4 = 2, which we add here. */ - /* 4-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We must also scale the output by 8/4 = 2, which we add here. + * 4-point FDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. + */ dataptr = data; for (ctr = 0; ctr < DCTSIZE; ctr++) { @@ -4033,7 +4084,7 @@ jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]); tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+1)); dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+1)); @@ -4046,10 +4097,10 @@ jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ - CONST_BITS-PASS1_BITS-1); + CONST_BITS-PASS1_BITS-1); dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ - CONST_BITS-PASS1_BITS-1); + CONST_BITS-PASS1_BITS-1); dataptr += DCTSIZE; /* advance pointer to next row */ } @@ -4057,12 +4108,13 @@ jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pass 2: process columns. * We remove the PASS1_BITS scaling, but leave the results scaled up * by an overall factor of 8. + * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */ dataptr = data; for (ctr = 0; ctr < 4; ctr++) { /* Even part per LL&M figure 1 --- note that published figure is faulty; - * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". + * rotator "c1" should be "c6". */ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; @@ -4084,47 +4136,49 @@ jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS); - z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS+PASS1_BITS-1); + dataptr[DCTSIZE*2] = (DCTELEM) - RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), CONST_BITS+PASS1_BITS); + RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */ + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*6] = (DCTELEM) - RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), CONST_BITS+PASS1_BITS); + RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */ + CONST_BITS+PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). - * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). * i0..i3 in the paper are tmp0..tmp3 here. */ - tmp10 = tmp0 + tmp3; - tmp11 = tmp1 + tmp2; tmp12 = tmp0 + tmp2; tmp13 = tmp1 + tmp3; - z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ + + z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */ /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS+PASS1_BITS-1); - tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ - tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ - tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ - tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ - tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */ - tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */ - tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */ - tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ - + tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */ + tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */ tmp12 += z1; tmp13 += z1; - dataptr[DCTSIZE*1] = (DCTELEM) - RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*3] = (DCTELEM) - RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*5] = (DCTELEM) - RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS+PASS1_BITS); - dataptr[DCTSIZE*7] = (DCTELEM) - RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS+PASS1_BITS); + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp0 += z1 + tmp12; + tmp3 += z1 + tmp13; + + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */ + tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp1 += z1 + tmp13; + tmp2 += z1 + tmp12; + + dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS+PASS1_BITS); + dataptr[DCTSIZE*7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } @@ -4150,12 +4204,13 @@ jpeg_fdct_3x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ - /* We scale the results further by 2 as part of output adaption */ - /* scaling for different DCT size. */ - /* 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6). */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * We scale the results further by 2 as part of output adaption + * scaling for different DCT size. + * 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6). + */ dataptr = data; for (ctr = 0; ctr < 6; ctr++) { @@ -4168,18 +4223,18 @@ jpeg_fdct_3x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+1)); dataptr[2] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */ - CONST_BITS-PASS1_BITS-1); + CONST_BITS-PASS1_BITS-1); /* Odd part */ dataptr[1] = (DCTELEM) DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */ - CONST_BITS-PASS1_BITS-1); + CONST_BITS-PASS1_BITS-1); dataptr += DCTSIZE; /* advance pointer to next row */ } @@ -4209,13 +4264,13 @@ jpeg_fdct_3x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); /* Odd part */ @@ -4223,13 +4278,13 @@ jpeg_fdct_3x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */ - CONST_BITS+PASS1_BITS); + CONST_BITS+PASS1_BITS); dataptr++; /* advance pointer to next column */ } @@ -4255,9 +4310,10 @@ jpeg_fdct_2x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - /* Pass 1: process rows. */ - /* Note results are scaled up by sqrt(8) compared to a true DCT. */ - /* We must also scale the output by (8/2)*(8/4) = 2**3, which we add here. */ + /* Pass 1: process rows. + * Note results are scaled up by sqrt(8) compared to a true DCT. + * We must also scale the output by (8/2)*(8/4) = 2**3, which we add here. + */ dataptr = data; for (ctr = 0; ctr < 4; ctr++) { @@ -4268,7 +4324,7 @@ jpeg_fdct_2x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) tmp0 = GETJSAMPLE(elemptr[0]); tmp1 = GETJSAMPLE(elemptr[1]); - /* Apply unsigned->signed conversion */ + /* Apply unsigned->signed conversion. */ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 3); /* Odd part */ @@ -4305,10 +4361,10 @@ jpeg_fdct_2x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */ - CONST_BITS); + CONST_BITS); dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */ - CONST_BITS); + CONST_BITS); dataptr++; /* advance pointer to next column */ } @@ -4324,24 +4380,29 @@ jpeg_fdct_2x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) GLOBAL(void) jpeg_fdct_1x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { - INT32 tmp0, tmp1; + DCTELEM tmp0, tmp1; /* Pre-zero output coefficient block. */ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2); - tmp0 = GETJSAMPLE(sample_data[0][start_col]); - tmp1 = GETJSAMPLE(sample_data[1][start_col]); + /* Pass 1: empty. */ - /* We leave the results scaled up by an overall factor of 8. + /* Pass 2: process columns. + * We leave the results scaled up by an overall factor of 8. * We must also scale the output by (8/1)*(8/2) = 2**5. */ /* Even part */ - /* Apply unsigned->signed conversion */ - data[DCTSIZE*0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5); + + tmp0 = GETJSAMPLE(sample_data[0][start_col]); + tmp1 = GETJSAMPLE(sample_data[1][start_col]); + + /* Apply unsigned->signed conversion. */ + data[DCTSIZE*0] = (tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5; /* Odd part */ - data[DCTSIZE*1] = (DCTELEM) ((tmp0 - tmp1) << 5); + + data[DCTSIZE*1] = (tmp0 - tmp1) << 5; } #endif /* DCT_SCALING_SUPPORTED */ diff --git a/3rdparty/libjpeg/jidctflt.c b/3rdparty/libjpeg/jidctflt.c index 63e9ddc480..c7e832a3bb 100644 --- a/3rdparty/libjpeg/jidctflt.c +++ b/3rdparty/libjpeg/jidctflt.c @@ -2,7 +2,7 @@ * jidctflt.c * * Copyright (C) 1994-1998, Thomas G. Lane. - * Modified 2010 by Guido Vollbeding. + * Modified 2010-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -63,12 +63,14 @@ /* * Perform dequantization and inverse DCT on one block of coefficients. + * + * cK represents cos(K*pi/16). */ GLOBAL(void) jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FAST_FLOAT tmp10, tmp11, tmp12, tmp13; @@ -77,7 +79,7 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, FLOAT_MULT_TYPE * quantptr; FAST_FLOAT * wsptr; JSAMPROW outptr; - JSAMPLE *range_limit = cinfo->sample_range_limit; + JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ @@ -97,9 +99,9 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); @@ -186,13 +188,14 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Apply signed->unsigned and prepare float->int conversion */ - z5 = wsptr[0] + ((FAST_FLOAT) CENTERJSAMPLE + (FAST_FLOAT) 0.5); + /* Prepare range-limit and float->int conversion */ + z5 = wsptr[0] + (((FAST_FLOAT) RANGE_CENTER) + ((FAST_FLOAT) 0.5)); tmp10 = z5 + wsptr[4]; tmp11 = z5 - wsptr[4]; tmp13 = wsptr[2] + wsptr[6]; - tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + tmp12 = (wsptr[2] - wsptr[6]) * + ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ tmp0 = tmp10 + tmp13; tmp3 = tmp10 - tmp13; @@ -206,27 +209,27 @@ jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr, z11 = wsptr[1] + wsptr[7]; z12 = wsptr[1] - wsptr[7]; - tmp7 = z11 + z13; - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ tmp10 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ - tmp6 = tmp12 - tmp7; + tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; tmp4 = tmp10 - tmp5; /* Final output stage: float->int conversion and range-limit */ - outptr[0] = range_limit[((int) (tmp0 + tmp7)) & RANGE_MASK]; - outptr[7] = range_limit[((int) (tmp0 - tmp7)) & RANGE_MASK]; - outptr[1] = range_limit[((int) (tmp1 + tmp6)) & RANGE_MASK]; - outptr[6] = range_limit[((int) (tmp1 - tmp6)) & RANGE_MASK]; - outptr[2] = range_limit[((int) (tmp2 + tmp5)) & RANGE_MASK]; - outptr[5] = range_limit[((int) (tmp2 - tmp5)) & RANGE_MASK]; - outptr[3] = range_limit[((int) (tmp3 + tmp4)) & RANGE_MASK]; - outptr[4] = range_limit[((int) (tmp3 - tmp4)) & RANGE_MASK]; + outptr[0] = range_limit[(int) (tmp0 + tmp7) & RANGE_MASK]; + outptr[7] = range_limit[(int) (tmp0 - tmp7) & RANGE_MASK]; + outptr[1] = range_limit[(int) (tmp1 + tmp6) & RANGE_MASK]; + outptr[6] = range_limit[(int) (tmp1 - tmp6) & RANGE_MASK]; + outptr[2] = range_limit[(int) (tmp2 + tmp5) & RANGE_MASK]; + outptr[5] = range_limit[(int) (tmp2 - tmp5) & RANGE_MASK]; + outptr[3] = range_limit[(int) (tmp3 + tmp4) & RANGE_MASK]; + outptr[4] = range_limit[(int) (tmp3 - tmp4) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } diff --git a/3rdparty/libjpeg/jidctfst.c b/3rdparty/libjpeg/jidctfst.c index 4012251888..474cc45fd7 100644 --- a/3rdparty/libjpeg/jidctfst.c +++ b/3rdparty/libjpeg/jidctfst.c @@ -2,6 +2,7 @@ * jidctfst.c * * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -129,45 +130,20 @@ #define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval)) #else #define DEQUANTIZE(coef,quantval) \ - DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) -#endif - - -/* Like DESCALE, but applies to a DCTELEM and produces an int. - * We assume that int right shift is unsigned if INT32 right shift is. - */ - -#ifdef RIGHT_SHIFT_IS_UNSIGNED -#define ISHIFT_TEMPS DCTELEM ishift_temp; -#if BITS_IN_JSAMPLE == 8 -#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */ -#else -#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */ -#endif -#define IRIGHT_SHIFT(x,shft) \ - ((ishift_temp = (x)) < 0 ? \ - (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \ - (ishift_temp >> (shft))) -#else -#define ISHIFT_TEMPS -#define IRIGHT_SHIFT(x,shft) ((x) >> (shft)) -#endif - -#ifdef USE_ACCURATE_ROUNDING -#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n)) -#else -#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n)) + DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS) #endif /* * Perform dequantization and inverse DCT on one block of coefficients. + * + * cK represents cos(K*pi/16). */ GLOBAL(void) jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; @@ -180,7 +156,7 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, int ctr; int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS /* for DESCALE */ - ISHIFT_TEMPS /* for IDESCALE */ + ISHIFT_TEMPS /* for IRIGHT_SHIFT */ /* Pass 1: process columns from input, store into work array. */ @@ -196,11 +172,11 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, * With typical images and quantization tables, half or more of the * column DCT calculations can be simplified this way. */ - + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); @@ -212,13 +188,13 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, wsptr[DCTSIZE*5] = dcval; wsptr[DCTSIZE*6] = dcval; wsptr[DCTSIZE*7] = dcval; - + inptr++; /* advance pointers to next column */ quantptr++; wsptr++; continue; } - + /* Even part */ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); @@ -236,7 +212,7 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp3 = tmp10 - tmp13; tmp1 = tmp11 + tmp12; tmp2 = tmp11 - tmp12; - + /* Odd part */ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); @@ -253,12 +229,12 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + tmp10 = z5 - MULTIPLY(z12, FIX_1_082392200); /* 2*(c2-c6) */ + tmp12 = z5 - MULTIPLY(z10, FIX_2_613125930); /* 2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; + tmp4 = tmp10 - tmp5; wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7); wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7); @@ -266,21 +242,28 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6); wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5); wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5); - wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4); - wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4); + wsptr[DCTSIZE*3] = (int) (tmp3 + tmp4); + wsptr[DCTSIZE*4] = (int) (tmp3 - tmp4); inptr++; /* advance pointers to next column */ quantptr++; wsptr++; } - - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ + + /* Pass 2: process rows from work array, store into output array. + * Note that we must descale the results by a factor of 8 == 2**3, + * and also undo the PASS1_BITS scaling. + */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { outptr = output_buf[ctr] + output_col; + + /* Add range center and fudge factor for final descale and range-limit. */ + z5 = (DCTELEM) wsptr[0] + + ((((DCTELEM) RANGE_CENTER) << (PASS1_BITS+3)) + + (1 << (PASS1_BITS+2))); + /* Rows of zeroes can be exploited in the same way as we did with columns. * However, the column calculation has created many nonzero AC terms, so * the simplification applies less often (typically 5% to 10% of the time). @@ -288,14 +271,14 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, * test takes more time than it's worth. In that case this section * may be commented out. */ - + #ifndef NO_ZERO_ROW_TEST if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; - + JSAMPLE dcval = range_limit[(int) IRIGHT_SHIFT(z5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[0] = dcval; outptr[1] = dcval; outptr[2] = dcval; @@ -309,15 +292,15 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, continue; } #endif - + /* Even part */ - tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]); - tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]); + tmp10 = z5 + (DCTELEM) wsptr[4]; + tmp11 = z5 - (DCTELEM) wsptr[4]; - tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]); - tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562) - - tmp13; + tmp13 = (DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]; + tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], + FIX_1_414213562) - tmp13; /* 2*c4 */ tmp0 = tmp10 + tmp13; tmp3 = tmp10 - tmp13; @@ -335,31 +318,31 @@ jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */ + tmp10 = z5 - MULTIPLY(z12, FIX_1_082392200); /* 2*(c2-c6) */ + tmp12 = z5 - MULTIPLY(z10, FIX_2_613125930); /* 2*(c2+c6) */ tmp6 = tmp12 - tmp7; /* phase 2 */ tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; + tmp4 = tmp10 - tmp5; /* Final output stage: scale down by a factor of 8 and range-limit */ - outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) - & RANGE_MASK]; - outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) - & RANGE_MASK]; - outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) - & RANGE_MASK]; - outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) - & RANGE_MASK]; - outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) - & RANGE_MASK]; - outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) - & RANGE_MASK]; - outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) - & RANGE_MASK]; - outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) - & RANGE_MASK]; + outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[7] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp7, PASS1_BITS+3) + & RANGE_MASK]; + outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp1 + tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[6] = range_limit[(int) IRIGHT_SHIFT(tmp1 - tmp6, PASS1_BITS+3) + & RANGE_MASK]; + outptr[2] = range_limit[(int) IRIGHT_SHIFT(tmp2 + tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[5] = range_limit[(int) IRIGHT_SHIFT(tmp2 - tmp5, PASS1_BITS+3) + & RANGE_MASK]; + outptr[3] = range_limit[(int) IRIGHT_SHIFT(tmp3 + tmp4, PASS1_BITS+3) + & RANGE_MASK]; + outptr[4] = range_limit[(int) IRIGHT_SHIFT(tmp3 - tmp4, PASS1_BITS+3) + & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } diff --git a/3rdparty/libjpeg/jidctint.c b/3rdparty/libjpeg/jidctint.c index 64c6f97d7e..de233ec996 100644 --- a/3rdparty/libjpeg/jidctint.c +++ b/3rdparty/libjpeg/jidctint.c @@ -2,7 +2,7 @@ * jidctint.c * * Copyright (C) 1991-1998, Thomas G. Lane. - * Modification developed 2002-2009 by Guido Vollbeding. + * Modification developed 2002-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -165,12 +165,14 @@ /* * Perform dequantization and inverse DCT on one block of coefficients. + * + * cK represents sqrt(2) * cos(K*pi/16). */ GLOBAL(void) jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; @@ -184,9 +186,10 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS - /* Pass 1: process columns from input, store into work array. */ - /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* Pass 1: process columns from input, store into work array. + * Note results are scaled up by sqrt(8) compared to a true IDCT; + * furthermore, we scale the results by 2**PASS1_BITS. + */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; @@ -202,9 +205,9 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; @@ -223,15 +226,9 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, continue; } - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ - - z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); @@ -243,6 +240,13 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp0 = z2 + z3; tmp1 = z2 - z3; + z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + tmp10 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; tmp11 = tmp1 + tmp3; @@ -260,21 +264,21 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; @@ -294,13 +298,20 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, wsptr++; } - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ + /* Pass 2: process rows from work array, store into output array. + * Note that we must descale the results by a factor of 8 == 2**3, + * and also undo the PASS1_BITS scaling. + */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { outptr = output_buf[ctr] + output_col; + + /* Add range center and fudge factor for final descale and range-limit. */ + z2 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); + /* Rows of zeroes can be exploited in the same way as we did with columns. * However, the column calculation has created many nonzero AC terms, so * the simplification applies less often (typically 5% to 10% of the time). @@ -311,10 +322,10 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, #ifndef NO_ZERO_ROW_TEST if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && - wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { /* AC terms all zero */ - JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) - & RANGE_MASK]; + JSAMPLE dcval = range_limit[(int) RIGHT_SHIFT(z2, PASS1_BITS+3) + & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; @@ -330,23 +341,22 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, } #endif - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[6]; - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); - - /* Add fudge factor here for final descale. */ - z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); z3 = (INT32) wsptr[4]; tmp0 = (z2 + z3) << CONST_BITS; tmp1 = (z2 - z3) << CONST_BITS; + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + tmp10 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; tmp11 = tmp1 + tmp3; @@ -364,50 +374,50 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } @@ -426,8 +436,8 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3; @@ -502,8 +512,10 @@ jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - tmp13 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp13 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp13 <<= CONST_BITS; z1 = (INT32) wsptr[2]; @@ -539,26 +551,26 @@ jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 7; /* advance pointer to next row */ } @@ -575,8 +587,8 @@ jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; INT32 z1, z2, z3; @@ -638,8 +650,10 @@ jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; tmp2 = (INT32) wsptr[4]; tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ @@ -663,23 +677,23 @@ jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 6; /* advance pointer to next row */ } @@ -696,8 +710,8 @@ jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp10, tmp11, tmp12; INT32 z1, z2, z3; @@ -757,8 +771,10 @@ jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - tmp12 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp12 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp12 <<= CONST_BITS; tmp0 = (INT32) wsptr[2]; tmp1 = (INT32) wsptr[4]; @@ -781,20 +797,20 @@ jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 5; /* advance pointer to next row */ } @@ -811,8 +827,8 @@ jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp2, tmp10, tmp12; INT32 z1, z2, z3; @@ -835,7 +851,7 @@ jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - + tmp10 = (tmp0 + tmp2) << PASS1_BITS; tmp12 = (tmp0 - tmp2) << PASS1_BITS; @@ -849,9 +865,9 @@ jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); /* Final output stage */ @@ -869,8 +885,10 @@ jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp2 = (INT32) wsptr[2]; tmp10 = (tmp0 + tmp2) << CONST_BITS; @@ -889,17 +907,17 @@ jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 4; /* advance pointer to next row */ } @@ -916,8 +934,8 @@ jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp2, tmp10, tmp12; JCOEFPTR inptr; @@ -966,8 +984,10 @@ jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; tmp2 = (INT32) wsptr[2]; tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ @@ -982,14 +1002,14 @@ jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 3; /* advance pointer to next row */ } @@ -1005,14 +1025,14 @@ jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { - INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; ISLOW_MULT_TYPE * quantptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); - SHIFT_TEMPS + ISHIFT_TEMPS /* Pass 1: process columns from input. */ @@ -1021,8 +1041,8 @@ jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Column 0 */ tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); - /* Add fudge factor here for final descale. */ - tmp4 += ONE << 2; + /* Add range center and fudge factor for final descale and range-limit. */ + tmp4 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); tmp0 = tmp4 + tmp5; tmp2 = tmp4 - tmp5; @@ -1039,14 +1059,14 @@ jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Row 0 */ outptr = output_buf[0] + output_col; - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; + outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; /* Row 1 */ outptr = output_buf[1] + output_col; - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp2 + tmp3, 3) & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2 - tmp3, 3) & RANGE_MASK]; + outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp2 + tmp3, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp2 - tmp3, 3) & RANGE_MASK]; } @@ -1060,20 +1080,24 @@ jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { - int dcval; + DCTELEM dcval; ISLOW_MULT_TYPE * quantptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); - SHIFT_TEMPS + ISHIFT_TEMPS /* 1x1 is trivial: just take the DC coefficient divided by 8. */ - quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; - dcval = DEQUANTIZE(coef_block[0], quantptr[0]); - dcval = (int) DESCALE((INT32) dcval, 3); - output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; + quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; + + dcval = DEQUANTIZE(coef_block[0], quantptr[0]); + /* Add range center and fudge factor for descale and range-limit. */ + dcval += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); + + output_buf[0][output_col] = + range_limit[(int) IRIGHT_SHIFT(dcval, 3) & RANGE_MASK]; } @@ -1087,8 +1111,8 @@ jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13, tmp14; INT32 z1, z2, z3, z4; @@ -1172,8 +1196,10 @@ jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; z1 = (INT32) wsptr[2]; @@ -1216,32 +1242,32 @@ jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -1258,8 +1284,8 @@ jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14; INT32 tmp20, tmp21, tmp22, tmp23, tmp24; @@ -1292,7 +1318,7 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = z3 - z2; tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); @@ -1355,8 +1381,10 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + z3 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); z3 <<= CONST_BITS; z4 = (INT32) wsptr[4]; z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ @@ -1408,35 +1436,35 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -1453,8 +1481,8 @@ jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; @@ -1492,13 +1520,13 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, z4 -= z2; tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ tmp21 = tmp20 + tmp23 + tmp25 - - MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ + MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ tmp24 += tmp25; tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ - MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ + MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ /* Odd part */ @@ -1514,7 +1542,7 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ + MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ @@ -1522,8 +1550,8 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 += z1; tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ - MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ - MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ + MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ + MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ /* Final output stage */ @@ -1548,8 +1576,10 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - tmp10 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp10 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp10 <<= CONST_BITS; z1 = (INT32) wsptr[2]; @@ -1563,13 +1593,13 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, z4 -= z2; tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */ tmp21 = tmp20 + tmp23 + tmp25 - - MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ + MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */ tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */ tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */ tmp24 += tmp25; tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */ tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */ - MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ + MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */ tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */ /* Odd part */ @@ -1585,7 +1615,7 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */ tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */ tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ + MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */ z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */ tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */ tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */ @@ -1593,44 +1623,44 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 += z1; tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */ tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */ - MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ - MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ + MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */ + MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -1647,8 +1677,8 @@ jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; @@ -1720,7 +1750,7 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ - MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ z1 -= z4; z2 -= z3; @@ -1752,8 +1782,10 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + z3 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); z3 <<= CONST_BITS; z4 = (INT32) wsptr[4]; @@ -1801,7 +1833,7 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ - MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ z1 -= z4; z2 -= z3; @@ -1812,41 +1844,41 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -1863,8 +1895,8 @@ jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; @@ -1930,7 +1962,7 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp15 = z1 + z4; tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ + MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ @@ -1942,11 +1974,11 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp13 += tmp14; tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ - MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ + MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ tmp14 += z1; tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ - MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ + MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ /* Final output stage */ @@ -1973,8 +2005,10 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + z1 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); z1 <<= CONST_BITS; z2 = (INT32) wsptr[2]; @@ -2016,7 +2050,7 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp15 = z1 + z4; tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */ tmp10 = tmp11 + tmp12 + tmp13 - - MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ + MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */ tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */ tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */ tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */ @@ -2028,53 +2062,53 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp13 += tmp14; tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */ tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */ - MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ + MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */ z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */ tmp14 += z1; tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */ - MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ + MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */ /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -2091,8 +2125,8 @@ jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; @@ -2128,7 +2162,7 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp12 = z1 - z4; tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); @@ -2138,7 +2172,7 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ - MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ tmp20 = tmp10 + tmp13; tmp26 = tmp10 - tmp13; @@ -2200,8 +2234,10 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + z1 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); z1 <<= CONST_BITS; z4 = (INT32) wsptr[4]; z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ @@ -2222,7 +2258,7 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ - MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ tmp20 = tmp10 + tmp13; tmp26 = tmp10 - tmp13; @@ -2260,47 +2296,47 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -2317,8 +2353,8 @@ jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; @@ -2432,8 +2468,10 @@ jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + z1 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); z1 <<= CONST_BITS; z2 = (INT32) wsptr[2]; @@ -2499,50 +2537,50 @@ jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -2559,8 +2597,8 @@ jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; @@ -2632,9 +2670,9 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ tmp0 = tmp1 + tmp2 + tmp3 - - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ tmp13 = tmp10 + tmp11 + tmp12 - - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ @@ -2683,8 +2721,10 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; z1 = (INT32) wsptr[4]; @@ -2732,9 +2772,9 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ tmp0 = tmp1 + tmp2 + tmp3 - - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ tmp13 = tmp10 + tmp11 + tmp12 - - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ @@ -2758,53 +2798,53 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -2820,8 +2860,8 @@ jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; @@ -2835,9 +2875,11 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, int workspace[8*8]; /* buffers data between passes */ SHIFT_TEMPS - /* Pass 1: process columns from input, store into work array. */ - /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* Pass 1: process columns from input, store into work array. + * Note results are scaled up by sqrt(8) compared to a true IDCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; @@ -2853,9 +2895,9 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; @@ -2874,15 +2916,16 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, continue; } - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); @@ -2911,21 +2954,21 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; @@ -2948,14 +2991,17 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 2: process 8 rows from work array, store into output array. * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). */ + wsptr = workspace; for (ctr = 0; ctr < 8; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ - /* Add fudge factor here for final descale. */ - tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; z1 = (INT32) wsptr[4]; @@ -3003,9 +3049,9 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ tmp0 = tmp1 + tmp2 + tmp3 - - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ tmp13 = tmp10 + tmp11 + tmp12 - - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ @@ -3029,53 +3075,53 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -3091,8 +3137,8 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; @@ -3109,6 +3155,7 @@ jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 1: process columns from input, store into work array. * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -3164,14 +3211,17 @@ jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 2: process 7 rows from work array, store into output array. * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). */ + wsptr = workspace; for (ctr = 0; ctr < 7; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ - /* Add fudge factor here for final descale. */ - z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + z1 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); z1 <<= CONST_BITS; z4 = (INT32) wsptr[4]; z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */ @@ -3192,7 +3242,7 @@ jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ - MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ tmp20 = tmp10 + tmp13; tmp26 = tmp10 - tmp13; @@ -3230,47 +3280,47 @@ jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -3286,8 +3336,8 @@ jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; @@ -3304,6 +3354,7 @@ jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 1: process columns from input, store into work array. * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -3346,14 +3397,17 @@ jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 2: process 6 rows from work array, store into output array. * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). */ + wsptr = workspace; for (ctr = 0; ctr < 6; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ - /* Add fudge factor here for final descale. */ - z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + z3 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); z3 <<= CONST_BITS; z4 = (INT32) wsptr[4]; @@ -3401,7 +3455,7 @@ jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ - MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ z1 -= z4; z2 -= z3; @@ -3412,41 +3466,41 @@ jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -3462,8 +3516,8 @@ jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14; INT32 tmp20, tmp21, tmp22, tmp23, tmp24; @@ -3480,6 +3534,7 @@ jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 1: process columns from input, store into work array. * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -3520,14 +3575,17 @@ jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 2: process 5 rows from work array, store into output array. * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). */ + wsptr = workspace; for (ctr = 0; ctr < 5; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ - /* Add fudge factor here for final descale. */ - z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + z3 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); z3 <<= CONST_BITS; z4 = (INT32) wsptr[4]; z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */ @@ -3579,35 +3637,35 @@ jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 8; /* advance pointer to next row */ } @@ -3623,8 +3681,8 @@ jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; @@ -3639,8 +3697,10 @@ jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. - * 4-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + * 4-point IDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -3663,9 +3723,9 @@ jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Add fudge factor here for final descale. */ z1 += ONE << (CONST_BITS-PASS1_BITS-1); tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); /* Final output stage */ @@ -3675,31 +3735,36 @@ jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, wsptr[8*2] = (int) (tmp12 - tmp2); } - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ + /* Pass 2: process rows from work array, store into output array. + * Note that we must descale the results by a factor of 8 == 2**3, + * and also undo the PASS1_BITS scaling. + * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ wsptr = workspace; for (ctr = 0; ctr < 4; ctr++) { outptr = output_buf[ctr] + output_col; - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[6]; - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); - - /* Add fudge factor here for final descale. */ - z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + z2 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); z3 = (INT32) wsptr[4]; tmp0 = (z2 + z3) << CONST_BITS; tmp1 = (z2 - z3) << CONST_BITS; + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + tmp10 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; tmp11 = tmp1 + tmp3; @@ -3717,50 +3782,50 @@ jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } @@ -3776,8 +3841,8 @@ jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; INT32 z1, z2, z3; @@ -3793,6 +3858,7 @@ jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 1: process columns from input, store into work array. * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -3819,18 +3885,21 @@ jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, wsptr[6*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS); wsptr[6*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS); } - + /* Pass 2: process 3 rows from work array, store into output array. * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ + wsptr = workspace; for (ctr = 0; ctr < 3; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ - /* Add fudge factor here for final descale. */ - tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; tmp2 = (INT32) wsptr[4]; tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */ @@ -3854,23 +3923,23 @@ jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 6; /* advance pointer to next row */ } @@ -3886,8 +3955,8 @@ jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_4x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp2, tmp10, tmp12; INT32 z1, z2, z3; @@ -3924,14 +3993,15 @@ jpeg_idct_4x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, * 4-point IDCT kernel, * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. */ + wsptr = workspace; for (ctr = 0; ctr < 2; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ - /* Add fudge factor here for final descale. */ - tmp0 = wsptr[0] + (ONE << 2); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = wsptr[0] + ((((INT32) RANGE_CENTER) << 3) + (ONE << 2)); tmp2 = wsptr[2]; tmp10 = (tmp0 + tmp2) << CONST_BITS; @@ -3950,17 +4020,17 @@ jpeg_idct_4x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+3) - & RANGE_MASK]; + CONST_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+3) - & RANGE_MASK]; + CONST_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+3) - & RANGE_MASK]; + CONST_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+3) - & RANGE_MASK]; + CONST_BITS+3) + & RANGE_MASK]; wsptr += 4; /* advance pointer to next row */ } @@ -3976,14 +4046,14 @@ jpeg_idct_4x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_2x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { - INT32 tmp0, tmp10; + DCTELEM tmp0, tmp1; ISLOW_MULT_TYPE * quantptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); - SHIFT_TEMPS + ISHIFT_TEMPS /* Pass 1: empty. */ @@ -3994,18 +4064,18 @@ jpeg_idct_2x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - tmp10 = DEQUANTIZE(coef_block[0], quantptr[0]); - /* Add fudge factor here for final descale. */ - tmp10 += ONE << 2; + tmp0 = DEQUANTIZE(coef_block[0], quantptr[0]); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); /* Odd part */ - tmp0 = DEQUANTIZE(coef_block[1], quantptr[1]); + tmp1 = DEQUANTIZE(coef_block[1], quantptr[1]); /* Final output stage */ - outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, 3) & RANGE_MASK]; - outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, 3) & RANGE_MASK]; + outptr[0] = range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; + outptr[1] = range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; } @@ -4018,8 +4088,8 @@ jpeg_idct_2x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27; @@ -4036,6 +4106,7 @@ jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 1: process columns from input, store into work array. * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32). */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -4092,9 +4163,9 @@ jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */ tmp0 = tmp1 + tmp2 + tmp3 - - MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ + MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */ tmp13 = tmp10 + tmp11 + tmp12 - - MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ + MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */ @@ -4135,31 +4206,36 @@ jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS); } - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3, */ - /* and also undo the PASS1_BITS scaling. */ + /* Pass 2: process rows from work array, store into output array. + * Note that we must descale the results by a factor of 8 == 2**3, + * and also undo the PASS1_BITS scaling. + * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ wsptr = workspace; for (ctr = 0; ctr < 16; ctr++) { outptr = output_buf[ctr] + output_col; - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ - z2 = (INT32) wsptr[2]; - z3 = (INT32) wsptr[6]; - - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); - - /* Add fudge factor here for final descale. */ - z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + z2 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); z3 = (INT32) wsptr[4]; tmp0 = (z2 + z3) << CONST_BITS; tmp1 = (z2 - z3) << CONST_BITS; + z2 = (INT32) wsptr[2]; + z3 = (INT32) wsptr[6]; + + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ + tmp10 = tmp0 + tmp2; tmp13 = tmp0 - tmp2; tmp11 = tmp1 + tmp3; @@ -4177,50 +4253,50 @@ jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } @@ -4236,8 +4312,8 @@ jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26; @@ -4254,6 +4330,7 @@ jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 1: process columns from input, store into work array. * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28). */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -4274,7 +4351,7 @@ jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp12 = z1 - z4; tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); @@ -4284,7 +4361,7 @@ jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */ - MULTIPLY(z2, FIX(1.378756276)); /* c2 */ + MULTIPLY(z2, FIX(1.378756276)); /* c2 */ tmp20 = tmp10 + tmp13; tmp26 = tmp10 - tmp13; @@ -4341,14 +4418,17 @@ jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 2: process 14 rows from work array, store into output array. * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14). */ + wsptr = workspace; for (ctr = 0; ctr < 14; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ - /* Add fudge factor here for final descale. */ - tmp23 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp23 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp23 <<= CONST_BITS; z1 = (INT32) wsptr[2]; @@ -4384,26 +4464,26 @@ jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 7; /* advance pointer to next row */ } @@ -4419,8 +4499,8 @@ jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25; @@ -4437,6 +4517,7 @@ jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 1: process columns from input, store into work array. * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24). */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -4493,7 +4574,7 @@ jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */ - MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ + MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */ z1 -= z4; z2 -= z3; @@ -4520,14 +4601,17 @@ jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 2: process 12 rows from work array, store into output array. * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ + wsptr = workspace; for (ctr = 0; ctr < 12; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ - /* Add fudge factor here for final descale. */ - tmp10 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp10 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp10 <<= CONST_BITS; tmp12 = (INT32) wsptr[4]; tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */ @@ -4551,23 +4635,23 @@ jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 6; /* advance pointer to next row */ } @@ -4583,8 +4667,8 @@ jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp10, tmp11, tmp12, tmp13, tmp14; INT32 tmp20, tmp21, tmp22, tmp23, tmp24; @@ -4601,6 +4685,7 @@ jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 1: process columns from input, store into work array. * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20). */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -4618,7 +4703,7 @@ jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp11 = z3 - z2; tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */ - CONST_BITS-PASS1_BITS); + CONST_BITS-PASS1_BITS); z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); @@ -4676,14 +4761,17 @@ jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 2: process 10 rows from work array, store into output array. * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10). */ + wsptr = workspace; for (ctr = 0; ctr < 10; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ - /* Add fudge factor here for final descale. */ - tmp12 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp12 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp12 <<= CONST_BITS; tmp13 = (INT32) wsptr[2]; tmp14 = (INT32) wsptr[4]; @@ -4706,20 +4794,20 @@ jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp13, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp14, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 5; /* advance pointer to next row */ } @@ -4735,8 +4823,8 @@ jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; @@ -4750,9 +4838,11 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, int workspace[4*8]; /* buffers data between passes */ SHIFT_TEMPS - /* Pass 1: process columns from input, store into work array. */ - /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ - /* furthermore, we scale the results by 2**PASS1_BITS. */ + /* Pass 1: process columns from input, store into work array. + * Note results are scaled up by sqrt(8) compared to a true IDCT; + * furthermore, we scale the results by 2**PASS1_BITS. + * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + */ inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; @@ -4768,9 +4858,9 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, */ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { /* AC terms all zero */ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS; @@ -4789,15 +4879,16 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, continue; } - /* Even part: reverse the even part of the forward DCT. */ - /* The rotator is sqrt(2)*c(-6). */ + /* Even part: reverse the even part of the forward DCT. + * The rotator is c(-6). + */ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - z1 = MULTIPLY(z2 + z3, FIX_0_541196100); - tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); - tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); + z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */ + tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */ + tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */ z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); @@ -4826,21 +4917,21 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, z2 = tmp0 + tmp2; z3 = tmp1 + tmp3; - z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */ - z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ - z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ + z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */ + z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */ + z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */ z2 += z1; z3 += z1; - z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ - tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ - tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ + z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */ + tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */ + tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* c1+c3-c5-c7 */ tmp0 += z1 + z2; tmp3 += z1 + z3; - z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ - tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ - tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ + z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */ + tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */ + tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */ tmp1 += z1 + z3; tmp2 += z1 + z2; @@ -4861,16 +4952,20 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, } /* Pass 2: process 8 rows from work array, store into output array. - * 4-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16). + * 4-point IDCT kernel, + * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. */ + wsptr = workspace; for (ctr = 0; ctr < 8; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ - /* Add fudge factor here for final descale. */ - tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp2 = (INT32) wsptr[2]; tmp10 = (tmp0 + tmp2) << CONST_BITS; @@ -4889,17 +4984,17 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 4; /* advance pointer to next row */ } @@ -4915,8 +5010,8 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12; INT32 z1, z2, z3; @@ -4932,6 +5027,7 @@ jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 1: process columns from input, store into work array. * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -4974,14 +5070,17 @@ jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Pass 2: process 6 rows from work array, store into output array. * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6). */ + wsptr = workspace; for (ctr = 0; ctr < 6; ctr++) { outptr = output_buf[ctr] + output_col; /* Even part */ - /* Add fudge factor here for final descale. */ - tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 = (INT32) wsptr[0] + + ((((INT32) RANGE_CENTER) << (PASS1_BITS+3)) + + (ONE << (PASS1_BITS+2))); tmp0 <<= CONST_BITS; tmp2 = (INT32) wsptr[2]; tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */ @@ -4996,14 +5095,14 @@ jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2, - CONST_BITS+PASS1_BITS+3) - & RANGE_MASK]; + CONST_BITS+PASS1_BITS+3) + & RANGE_MASK]; wsptr += 3; /* advance pointer to next row */ } @@ -5019,8 +5118,8 @@ jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp2, tmp10, tmp12; INT32 z1, z2, z3; @@ -5037,6 +5136,7 @@ jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, * 4-point IDCT kernel, * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT]. */ + inptr = coef_block; quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table; wsptr = workspace; @@ -5075,8 +5175,10 @@ jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - /* Add fudge factor here for final descale. */ - tmp10 = wsptr[0] + (ONE << (CONST_BITS+2)); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp10 = wsptr[0] + + ((((INT32) RANGE_CENTER) << (CONST_BITS+3)) + + (ONE << (CONST_BITS+2))); /* Odd part */ @@ -5085,9 +5187,9 @@ jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Final output stage */ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+3) - & RANGE_MASK]; + & RANGE_MASK]; outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+3) - & RANGE_MASK]; + & RANGE_MASK]; wsptr += 2; /* advance pointer to next row */ } @@ -5103,13 +5205,13 @@ jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, GLOBAL(void) jpeg_idct_1x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col) + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col) { - INT32 tmp0, tmp10; + DCTELEM tmp0, tmp1; ISLOW_MULT_TYPE * quantptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); - SHIFT_TEMPS + ISHIFT_TEMPS /* Process 1 column from input, store into output array. */ @@ -5117,20 +5219,20 @@ jpeg_idct_1x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */ - tmp10 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); - /* Add fudge factor here for final descale. */ - tmp10 += ONE << 2; + tmp0 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]); + /* Add range center and fudge factor for final descale and range-limit. */ + tmp0 += (((DCTELEM) RANGE_CENTER) << 3) + (1 << 2); /* Odd part */ - tmp0 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp1 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]); /* Final output stage */ - output_buf[0][output_col] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, 3) - & RANGE_MASK]; - output_buf[1][output_col] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, 3) - & RANGE_MASK]; + output_buf[0][output_col] = + range_limit[(int) IRIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK]; + output_buf[1][output_col] = + range_limit[(int) IRIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK]; } #endif /* IDCT_SCALING_SUPPORTED */ diff --git a/3rdparty/libjpeg/jmemansi.c b/3rdparty/libjpeg/jmemansi.c index 7049735577..2d93e49625 100644 --- a/3rdparty/libjpeg/jmemansi.c +++ b/3rdparty/libjpeg/jmemansi.c @@ -79,7 +79,7 @@ jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) GLOBAL(long) jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, - long max_bytes_needed, long already_allocated) + long max_bytes_needed, long already_allocated) { return cinfo->mem->max_memory_to_use - already_allocated; } @@ -95,8 +95,8 @@ jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, METHODDEF(void) read_backing_store (j_common_ptr cinfo, backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count) + void FAR * buffer_address, + long file_offset, long byte_count) { if (fseek(info->temp_file, file_offset, SEEK_SET)) ERREXIT(cinfo, JERR_TFILE_SEEK); @@ -108,8 +108,8 @@ read_backing_store (j_common_ptr cinfo, backing_store_ptr info, METHODDEF(void) write_backing_store (j_common_ptr cinfo, backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count) + void FAR * buffer_address, + long file_offset, long byte_count) { if (fseek(info->temp_file, file_offset, SEEK_SET)) ERREXIT(cinfo, JERR_TFILE_SEEK); @@ -139,7 +139,7 @@ close_backing_store (j_common_ptr cinfo, backing_store_ptr info) GLOBAL(void) jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, - long total_bytes_needed) + long total_bytes_needed) { if ((info->temp_file = tmpfile()) == NULL) ERREXITS(cinfo, JERR_TFILE_CREATE, ""); diff --git a/3rdparty/libjpeg/jmemmgr.c b/3rdparty/libjpeg/jmemmgr.c index ecbb2fa0d6..0a137cdde4 100644 --- a/3rdparty/libjpeg/jmemmgr.c +++ b/3rdparty/libjpeg/jmemmgr.c @@ -195,19 +195,19 @@ print_mem_stats (j_common_ptr cinfo, int pool_id) * This is helpful because message parm array can't handle longs. */ fprintf(stderr, "Freeing pool %d, total space = %ld\n", - pool_id, mem->total_space_allocated); + pool_id, mem->total_space_allocated); for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; lhdr_ptr = lhdr_ptr->hdr.next) { fprintf(stderr, " Large chunk used %ld\n", - (long) lhdr_ptr->hdr.bytes_used); + (long) lhdr_ptr->hdr.bytes_used); } for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; shdr_ptr = shdr_ptr->hdr.next) { fprintf(stderr, " Small chunk used %ld free %ld\n", - (long) shdr_ptr->hdr.bytes_used, - (long) shdr_ptr->hdr.bytes_left); + (long) shdr_ptr->hdr.bytes_used, + (long) shdr_ptr->hdr.bytes_left); } } @@ -239,16 +239,16 @@ out_of_memory (j_common_ptr cinfo, int which) * machines, but may be too small if longs are 64 bits or more. */ -static const size_t first_pool_slop[JPOOL_NUMPOOLS] = +static const size_t first_pool_slop[JPOOL_NUMPOOLS] = { - 1600, /* first PERMANENT pool */ - 16000 /* first IMAGE pool */ + 1600, /* first PERMANENT pool */ + 16000 /* first IMAGE pool */ }; -static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = +static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = { - 0, /* additional PERMANENT pools */ - 5000 /* additional IMAGE pools */ + 0, /* additional PERMANENT pools */ + 5000 /* additional IMAGE pools */ }; #define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ @@ -299,10 +299,10 @@ alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) for (;;) { hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); if (hdr_ptr != NULL) - break; + break; slop /= 2; if (slop < MIN_SLOP) /* give up when it gets real small */ - out_of_memory(cinfo, 2); /* jpeg_get_small failed */ + out_of_memory(cinfo, 2); /* jpeg_get_small failed */ } mem->total_space_allocated += min_request + slop; /* Success, initialize the new pool header and add to end of list */ @@ -361,7 +361,7 @@ alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + - SIZEOF(large_pool_hdr)); + SIZEOF(large_pool_hdr)); if (hdr_ptr == NULL) out_of_memory(cinfo, 4); /* jpeg_get_large failed */ mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); @@ -394,7 +394,7 @@ alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) METHODDEF(JSAMPARRAY) alloc_sarray (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, JDIMENSION numrows) + JDIMENSION samplesperrow, JDIMENSION numrows) /* Allocate a 2-D sample array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; @@ -405,7 +405,7 @@ alloc_sarray (j_common_ptr cinfo, int pool_id, /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / - ((long) samplesperrow * SIZEOF(JSAMPLE)); + ((long) samplesperrow * SIZEOF(JSAMPLE)); if (ltemp <= 0) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long) numrows) @@ -416,15 +416,15 @@ alloc_sarray (j_common_ptr cinfo, int pool_id, /* Get space for row pointers (small object) */ result = (JSAMPARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JSAMPROW))); + (size_t) (numrows * SIZEOF(JSAMPROW))); /* Get the rows themselves (large objects) */ currow = 0; while (currow < numrows) { rowsperchunk = MIN(rowsperchunk, numrows - currow); workspace = (JSAMPROW) alloc_large(cinfo, pool_id, - (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow - * SIZEOF(JSAMPLE))); + (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow + * SIZEOF(JSAMPLE))); for (i = rowsperchunk; i > 0; i--) { result[currow++] = workspace; workspace += samplesperrow; @@ -442,7 +442,7 @@ alloc_sarray (j_common_ptr cinfo, int pool_id, METHODDEF(JBLOCKARRAY) alloc_barray (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, JDIMENSION numrows) + JDIMENSION blocksperrow, JDIMENSION numrows) /* Allocate a 2-D coefficient-block array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; @@ -453,7 +453,7 @@ alloc_barray (j_common_ptr cinfo, int pool_id, /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / - ((long) blocksperrow * SIZEOF(JBLOCK)); + ((long) blocksperrow * SIZEOF(JBLOCK)); if (ltemp <= 0) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long) numrows) @@ -464,15 +464,15 @@ alloc_barray (j_common_ptr cinfo, int pool_id, /* Get space for row pointers (small object) */ result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, - (size_t) (numrows * SIZEOF(JBLOCKROW))); + (size_t) (numrows * SIZEOF(JBLOCKROW))); /* Get the rows themselves (large objects) */ currow = 0; while (currow < numrows) { rowsperchunk = MIN(rowsperchunk, numrows - currow); workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, - (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow - * SIZEOF(JBLOCK))); + (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow + * SIZEOF(JBLOCK))); for (i = rowsperchunk; i > 0; i--) { result[currow++] = workspace; workspace += blocksperrow; @@ -522,8 +522,8 @@ alloc_barray (j_common_ptr cinfo, int pool_id, METHODDEF(jvirt_sarray_ptr) request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION samplesperrow, JDIMENSION numrows, - JDIMENSION maxaccess) + JDIMENSION samplesperrow, JDIMENSION numrows, + JDIMENSION maxaccess) /* Request a virtual 2-D sample array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; @@ -535,7 +535,7 @@ request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, /* get control block */ result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, - SIZEOF(struct jvirt_sarray_control)); + SIZEOF(struct jvirt_sarray_control)); result->mem_buffer = NULL; /* marks array not yet realized */ result->rows_in_array = numrows; @@ -552,8 +552,8 @@ request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero, METHODDEF(jvirt_barray_ptr) request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, - JDIMENSION blocksperrow, JDIMENSION numrows, - JDIMENSION maxaccess) + JDIMENSION blocksperrow, JDIMENSION numrows, + JDIMENSION maxaccess) /* Request a virtual 2-D coefficient-block array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; @@ -565,7 +565,7 @@ request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero, /* get control block */ result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, - SIZEOF(struct jvirt_barray_control)); + SIZEOF(struct jvirt_barray_control)); result->mem_buffer = NULL; /* marks array not yet realized */ result->rows_in_array = numrows; @@ -599,17 +599,17 @@ realize_virt_arrays (j_common_ptr cinfo) for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->mem_buffer == NULL) { /* if not realized yet */ space_per_minheight += (long) sptr->maxaccess * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); maximum_space += (long) sptr->rows_in_array * - (long) sptr->samplesperrow * SIZEOF(JSAMPLE); + (long) sptr->samplesperrow * SIZEOF(JSAMPLE); } } for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->mem_buffer == NULL) { /* if not realized yet */ space_per_minheight += (long) bptr->maxaccess * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); + (long) bptr->blocksperrow * SIZEOF(JBLOCK); maximum_space += (long) bptr->rows_in_array * - (long) bptr->blocksperrow * SIZEOF(JBLOCK); + (long) bptr->blocksperrow * SIZEOF(JBLOCK); } } @@ -618,7 +618,7 @@ realize_virt_arrays (j_common_ptr cinfo) /* Determine amount of memory to actually use; this is system-dependent. */ avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space, - mem->total_space_allocated); + mem->total_space_allocated); /* If the maximum space needed is available, make all the buffers full * height; otherwise parcel it out with the same number of minheights @@ -641,19 +641,19 @@ realize_virt_arrays (j_common_ptr cinfo) if (sptr->mem_buffer == NULL) { /* if not realized yet */ minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L; if (minheights <= max_minheights) { - /* This buffer fits in memory */ - sptr->rows_in_mem = sptr->rows_in_array; + /* This buffer fits in memory */ + sptr->rows_in_mem = sptr->rows_in_array; } else { - /* It doesn't fit in memory, create backing store. */ - sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); - jpeg_open_backing_store(cinfo, & sptr->b_s_info, - (long) sptr->rows_in_array * - (long) sptr->samplesperrow * - (long) SIZEOF(JSAMPLE)); - sptr->b_s_open = TRUE; + /* It doesn't fit in memory, create backing store. */ + sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess); + jpeg_open_backing_store(cinfo, & sptr->b_s_info, + (long) sptr->rows_in_array * + (long) sptr->samplesperrow * + (long) SIZEOF(JSAMPLE)); + sptr->b_s_open = TRUE; } sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, - sptr->samplesperrow, sptr->rows_in_mem); + sptr->samplesperrow, sptr->rows_in_mem); sptr->rowsperchunk = mem->last_rowsperchunk; sptr->cur_start_row = 0; sptr->first_undef_row = 0; @@ -665,19 +665,19 @@ realize_virt_arrays (j_common_ptr cinfo) if (bptr->mem_buffer == NULL) { /* if not realized yet */ minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L; if (minheights <= max_minheights) { - /* This buffer fits in memory */ - bptr->rows_in_mem = bptr->rows_in_array; + /* This buffer fits in memory */ + bptr->rows_in_mem = bptr->rows_in_array; } else { - /* It doesn't fit in memory, create backing store. */ - bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); - jpeg_open_backing_store(cinfo, & bptr->b_s_info, - (long) bptr->rows_in_array * - (long) bptr->blocksperrow * - (long) SIZEOF(JBLOCK)); - bptr->b_s_open = TRUE; + /* It doesn't fit in memory, create backing store. */ + bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess); + jpeg_open_backing_store(cinfo, & bptr->b_s_info, + (long) bptr->rows_in_array * + (long) bptr->blocksperrow * + (long) SIZEOF(JBLOCK)); + bptr->b_s_open = TRUE; } bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, - bptr->blocksperrow, bptr->rows_in_mem); + bptr->blocksperrow, bptr->rows_in_mem); bptr->rowsperchunk = mem->last_rowsperchunk; bptr->cur_start_row = 0; bptr->first_undef_row = 0; @@ -709,12 +709,12 @@ do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) byte_count = rows * bytesperrow; if (writing) (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); else (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); file_offset += byte_count; } } @@ -742,12 +742,12 @@ do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) byte_count = rows * bytesperrow; if (writing) (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); else (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, - (void FAR *) ptr->mem_buffer[i], - file_offset, byte_count); + (void FAR *) ptr->mem_buffer[i], + file_offset, byte_count); file_offset += byte_count; } } @@ -755,8 +755,8 @@ do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) METHODDEF(JSAMPARRAY) access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) /* Access the part of a virtual sample array starting at start_row */ /* and extending for num_rows rows. writable is true if */ /* caller intends to modify the accessed area. */ @@ -794,7 +794,7 @@ access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, ltemp = (long) end_row - (long) ptr->rows_in_mem; if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ + ltemp = 0; /* don't fall off front end of file */ ptr->cur_start_row = (JDIMENSION) ltemp; } /* Read in the selected part of the array. @@ -810,7 +810,7 @@ access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, if (ptr->first_undef_row < end_row) { if (ptr->first_undef_row < start_row) { if (writable) /* writer skipped over a section of array */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); undef_row = start_row; /* but reader is allowed to read ahead */ } else { undef_row = ptr->first_undef_row; @@ -822,12 +822,12 @@ access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ end_row -= ptr->cur_start_row; while (undef_row < end_row) { - FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); - undef_row++; + FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; } } else { if (! writable) /* reader looking at undefined data */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); } } /* Flag the buffer dirty if caller will write in it */ @@ -840,8 +840,8 @@ access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, METHODDEF(JBLOCKARRAY) access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, - JDIMENSION start_row, JDIMENSION num_rows, - boolean writable) + JDIMENSION start_row, JDIMENSION num_rows, + boolean writable) /* Access the part of a virtual block array starting at start_row */ /* and extending for num_rows rows. writable is true if */ /* caller intends to modify the accessed area. */ @@ -879,7 +879,7 @@ access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, ltemp = (long) end_row - (long) ptr->rows_in_mem; if (ltemp < 0) - ltemp = 0; /* don't fall off front end of file */ + ltemp = 0; /* don't fall off front end of file */ ptr->cur_start_row = (JDIMENSION) ltemp; } /* Read in the selected part of the array. @@ -895,7 +895,7 @@ access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, if (ptr->first_undef_row < end_row) { if (ptr->first_undef_row < start_row) { if (writable) /* writer skipped over a section of array */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); undef_row = start_row; /* but reader is allowed to read ahead */ } else { undef_row = ptr->first_undef_row; @@ -907,12 +907,12 @@ access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ end_row -= ptr->cur_start_row; while (undef_row < end_row) { - FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); - undef_row++; + FMEMZERO((void FAR *) ptr->mem_buffer[undef_row], bytesperrow); + undef_row++; } } else { if (! writable) /* reader looking at undefined data */ - ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); } } /* Flag the buffer dirty if caller will write in it */ @@ -950,15 +950,15 @@ free_pool (j_common_ptr cinfo, int pool_id) for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->b_s_open) { /* there may be no backing store */ - sptr->b_s_open = FALSE; /* prevent recursive close if error */ - (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); + sptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); } } mem->virt_sarray_list = NULL; for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->b_s_open) { /* there may be no backing store */ - bptr->b_s_open = FALSE; /* prevent recursive close if error */ - (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); + bptr->b_s_open = FALSE; /* prevent recursive close if error */ + (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); } } mem->virt_barray_list = NULL; @@ -971,8 +971,8 @@ free_pool (j_common_ptr cinfo, int pool_id) while (lhdr_ptr != NULL) { large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; space_freed = lhdr_ptr->hdr.bytes_used + - lhdr_ptr->hdr.bytes_left + - SIZEOF(large_pool_hdr); + lhdr_ptr->hdr.bytes_left + + SIZEOF(large_pool_hdr); jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); mem->total_space_allocated -= space_freed; lhdr_ptr = next_lhdr_ptr; @@ -985,8 +985,8 @@ free_pool (j_common_ptr cinfo, int pool_id) while (shdr_ptr != NULL) { small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; space_freed = shdr_ptr->hdr.bytes_used + - shdr_ptr->hdr.bytes_left + - SIZEOF(small_pool_hdr); + shdr_ptr->hdr.bytes_left + + SIZEOF(small_pool_hdr); jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); mem->total_space_allocated -= space_freed; shdr_ptr = next_shdr_ptr; @@ -1108,9 +1108,9 @@ jinit_memory_mgr (j_common_ptr cinfo) char ch = 'x'; if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { - if (ch == 'm' || ch == 'M') - max_to_use *= 1000L; - mem->pub.max_memory_to_use = max_to_use * 1000L; + if (ch == 'm' || ch == 'M') + max_to_use *= 1000L; + mem->pub.max_memory_to_use = max_to_use * 1000L; } } } diff --git a/3rdparty/libjpeg/jmemnobs.c b/3rdparty/libjpeg/jmemnobs.c index 3963805484..eb8c337725 100644 --- a/3rdparty/libjpeg/jmemnobs.c +++ b/3rdparty/libjpeg/jmemnobs.c @@ -71,7 +71,7 @@ jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) GLOBAL(long) jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, - long max_bytes_needed, long already_allocated) + long max_bytes_needed, long already_allocated) { return max_bytes_needed; } @@ -85,7 +85,7 @@ jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, GLOBAL(void) jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, - long total_bytes_needed) + long total_bytes_needed) { ERREXIT(cinfo, JERR_NO_BACKING_STORE); } diff --git a/3rdparty/libjpeg/jmemsys.h b/3rdparty/libjpeg/jmemsys.h index 6cfea6a42d..6c3c6d348f 100644 --- a/3rdparty/libjpeg/jmemsys.h +++ b/3rdparty/libjpeg/jmemsys.h @@ -46,7 +46,7 @@ EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, - size_t sizeofobject)); + size_t sizeofobject)); /* * These two functions are used to allocate and release large chunks of @@ -58,9 +58,9 @@ EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object, */ EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo, - size_t sizeofobject)); + size_t sizeofobject)); EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, - size_t sizeofobject)); + size_t sizeofobject)); /* * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may @@ -101,9 +101,9 @@ EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, */ EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo, - long min_bytes_needed, - long max_bytes_needed, - long already_allocated)); + long min_bytes_needed, + long max_bytes_needed, + long already_allocated)); /* @@ -139,15 +139,15 @@ typedef struct backing_store_struct * backing_store_ptr; typedef struct backing_store_struct { /* Methods for reading/writing/closing this backing-store object */ JMETHOD(void, read_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); JMETHOD(void, write_backing_store, (j_common_ptr cinfo, - backing_store_ptr info, - void FAR * buffer_address, - long file_offset, long byte_count)); + backing_store_ptr info, + void FAR * buffer_address, + long file_offset, long byte_count)); JMETHOD(void, close_backing_store, (j_common_ptr cinfo, - backing_store_ptr info)); + backing_store_ptr info)); /* Private fields for system-dependent backing-store management */ #ifdef USE_MSDOS_MEMMGR @@ -178,8 +178,8 @@ typedef struct backing_store_struct { */ EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo, - backing_store_ptr info, - long total_bytes_needed)); + backing_store_ptr info, + long total_bytes_needed)); /* diff --git a/3rdparty/libjpeg/jmorecfg.h b/3rdparty/libjpeg/jmorecfg.h index 2407edbef8..679d68bdc5 100644 --- a/3rdparty/libjpeg/jmorecfg.h +++ b/3rdparty/libjpeg/jmorecfg.h @@ -2,7 +2,7 @@ * jmorecfg.h * * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 1997-2012 by Guido Vollbeding. + * Modified 1997-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -15,13 +15,22 @@ /* * Define BITS_IN_JSAMPLE as either * 8 for 8-bit sample values (the usual setting) + * 9 for 9-bit sample values + * 10 for 10-bit sample values + * 11 for 11-bit sample values * 12 for 12-bit sample values - * Only 8 and 12 are legal data precisions for lossy JPEG according to the - * JPEG standard, and the IJG code does not support anything else! - * We do not support run-time selection of data precision, sorry. + * Only 8, 9, 10, 11, and 12 bits sample data precision are supported for + * full-feature DCT processing. Further depths up to 16-bit may be added + * later for the lossless modes of operation. + * Run-time selection and conversion of data precision will be added later + * and are currently not supported, sorry. + * Exception: The transcoding part (jpegtran) supports all settings in a + * single instance, since it operates on the level of DCT coefficients and + * not sample values. The DCT coefficients are of the same type (16 bits) + * in all cases (see below). */ -#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ +#define BITS_IN_JSAMPLE 8 /* use 8, 9, 10, 11, or 12 */ /* @@ -77,6 +86,48 @@ typedef char JSAMPLE; #endif /* BITS_IN_JSAMPLE == 8 */ +#if BITS_IN_JSAMPLE == 9 +/* JSAMPLE should be the smallest type that will hold the values 0..511. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 511 +#define CENTERJSAMPLE 256 + +#endif /* BITS_IN_JSAMPLE == 9 */ + + +#if BITS_IN_JSAMPLE == 10 +/* JSAMPLE should be the smallest type that will hold the values 0..1023. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 1023 +#define CENTERJSAMPLE 512 + +#endif /* BITS_IN_JSAMPLE == 10 */ + + +#if BITS_IN_JSAMPLE == 11 +/* JSAMPLE should be the smallest type that will hold the values 0..2047. + * On nearly all machines "short" will do nicely. + */ + +typedef short JSAMPLE; +#define GETJSAMPLE(value) ((int) (value)) + +#define MAXJSAMPLE 2047 +#define CENTERJSAMPLE 1024 + +#endif /* BITS_IN_JSAMPLE == 11 */ + + #if BITS_IN_JSAMPLE == 12 /* JSAMPLE should be the smallest type that will hold the values 0..4095. * On nearly all machines "short" will do nicely. @@ -252,7 +303,10 @@ typedef void noreturn_t; * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. */ -#ifdef HAVE_BOOLEAN +#ifndef HAVE_BOOLEAN +#if defined FALSE || defined TRUE || defined QGLOBAL_H +/* Qt3 defines FALSE and TRUE as "const" variables in qglobal.h */ +typedef int boolean; #ifndef FALSE /* in case these macros already exist */ #define FALSE 0 /* values of boolean */ #endif @@ -262,6 +316,7 @@ typedef void noreturn_t; #else typedef enum { FALSE = 0, TRUE = 1 } boolean; #endif +#endif /* @@ -299,11 +354,12 @@ typedef enum { FALSE = 0, TRUE = 1 } boolean; #define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ #define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ -/* Note: if you selected 12-bit data precision, it is dangerous to turn off - * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit - * precision, so jchuff.c normally uses entropy optimization to compute - * usable tables for higher precision. If you don't want to do optimization, - * you'll have to supply different default Huffman tables. +/* Note: if you selected more than 8-bit data precision, it is dangerous to + * turn off ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only + * good for 8-bit precision, so arithmetic coding is recommended for higher + * precision. The Huffman encoder normally uses entropy optimization to + * compute usable tables for higher precision. Otherwise, you'll have to + * supply different default Huffman tables. * The exact same statements apply for progressive JPEG: the default tables * don't work for progressive mode. (This may get fixed, however.) */ @@ -314,7 +370,7 @@ typedef enum { FALSE = 0, TRUE = 1 } boolean; #define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ +#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires DCT_ISLOW)*/ #define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ #define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ #undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ diff --git a/3rdparty/libjpeg/jpegint.h b/3rdparty/libjpeg/jpegint.h index e037926af4..18bb8879aa 100644 --- a/3rdparty/libjpeg/jpegint.h +++ b/3rdparty/libjpeg/jpegint.h @@ -2,7 +2,7 @@ * jpegint.h * * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 1997-2011 by Guido Vollbeding. + * Modified 1997-2013 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -15,11 +15,11 @@ /* Declarations for both compression & decompression */ typedef enum { /* Operating modes for buffer controllers */ - JBUF_PASS_THRU, /* Plain stripwise operation */ - /* Remaining modes require a full-image buffer to have been created */ - JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ - JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ - JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ + JBUF_PASS_THRU, /* Plain stripwise operation */ + /* Remaining modes require a full-image buffer to have been created */ + JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ + JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ + JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ } J_BUF_MODE; /* Values of global_state field (jdapi.c has some dependencies on ordering!) */ @@ -57,54 +57,54 @@ struct jpeg_comp_master { struct jpeg_c_main_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail)); + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail)); }; /* Compression preprocessing (downsampling input buffer control) */ struct jpeg_c_prep_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, - JDIMENSION *in_row_ctr, - JDIMENSION in_rows_avail, - JSAMPIMAGE output_buf, - JDIMENSION *out_row_group_ctr, - JDIMENSION out_row_groups_avail)); + JSAMPARRAY input_buf, + JDIMENSION *in_row_ctr, + JDIMENSION in_rows_avail, + JSAMPIMAGE output_buf, + JDIMENSION *out_row_group_ctr, + JDIMENSION out_row_groups_avail)); }; /* Coefficient buffer control */ struct jpeg_c_coef_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(boolean, compress_data, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf)); + JSAMPIMAGE input_buf)); }; /* Colorspace conversion */ struct jpeg_color_converter { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); JMETHOD(void, color_convert, (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows)); + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows)); }; /* Downsampling */ struct jpeg_downsampler { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); JMETHOD(void, downsample, (j_compress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION in_row_index, - JSAMPIMAGE output_buf, - JDIMENSION out_row_group_index)); + JSAMPIMAGE input_buf, JDIMENSION in_row_index, + JSAMPIMAGE output_buf, + JDIMENSION out_row_group_index)); boolean need_context_rows; /* TRUE if need rows above & below */ }; /* Forward DCT (also controls coefficient quantization) */ typedef JMETHOD(void, forward_DCT_ptr, - (j_compress_ptr cinfo, jpeg_component_info * compptr, - JSAMPARRAY sample_data, JBLOCKROW coef_blocks, - JDIMENSION start_row, JDIMENSION start_col, - JDIMENSION num_blocks)); + (j_compress_ptr cinfo, jpeg_component_info * compptr, + JSAMPARRAY sample_data, JBLOCKROW coef_blocks, + JDIMENSION start_row, JDIMENSION start_col, + JDIMENSION num_blocks)); struct jpeg_forward_dct { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); @@ -129,7 +129,7 @@ struct jpeg_marker_writer { /* These routines are exported to allow insertion of extra markers */ /* Probably only COM and APPn markers should be written this way */ JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker, - unsigned int datalen)); + unsigned int datalen)); JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val)); }; @@ -161,8 +161,8 @@ struct jpeg_input_controller { struct jpeg_d_main_controller { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, process_data, (j_decompress_ptr cinfo, - JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); + JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); }; /* Coefficient buffer control */ @@ -171,7 +171,7 @@ struct jpeg_d_coef_controller { JMETHOD(int, consume_data, (j_decompress_ptr cinfo)); JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo)); JMETHOD(int, decompress_data, (j_decompress_ptr cinfo, - JSAMPIMAGE output_buf)); + JSAMPIMAGE output_buf)); /* Pointer to array of coefficient virtual arrays, or NULL if none */ jvirt_barray_ptr *coef_arrays; }; @@ -180,12 +180,12 @@ struct jpeg_d_coef_controller { struct jpeg_d_post_controller { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); }; /* Marker reading & parsing */ @@ -211,15 +211,15 @@ struct jpeg_marker_reader { /* Entropy decoding */ struct jpeg_entropy_decoder { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); - JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, - JBLOCKROW *MCU_data)); + JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); + JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); }; /* Inverse DCT (also performs dequantization) */ typedef JMETHOD(void, inverse_DCT_method_ptr, - (j_decompress_ptr cinfo, jpeg_component_info * compptr, - JCOEFPTR coef_block, - JSAMPARRAY output_buf, JDIMENSION output_col)); + (j_decompress_ptr cinfo, jpeg_component_info * compptr, + JCOEFPTR coef_block, + JSAMPARRAY output_buf, JDIMENSION output_col)); struct jpeg_inverse_dct { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); @@ -231,12 +231,12 @@ struct jpeg_inverse_dct { struct jpeg_upsampler { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(void, upsample, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, - JDIMENSION *in_row_group_ctr, - JDIMENSION in_row_groups_avail, - JSAMPARRAY output_buf, - JDIMENSION *out_row_ctr, - JDIMENSION out_rows_avail)); + JSAMPIMAGE input_buf, + JDIMENSION *in_row_group_ctr, + JDIMENSION in_row_groups_avail, + JSAMPARRAY output_buf, + JDIMENSION *out_row_ctr, + JDIMENSION out_rows_avail)); boolean need_context_rows; /* TRUE if need rows above & below */ }; @@ -245,16 +245,16 @@ struct jpeg_upsampler { struct jpeg_color_deconverter { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(void, color_convert, (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows)); + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows)); }; /* Color quantization or color precision reduction */ struct jpeg_color_quantizer { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan)); JMETHOD(void, color_quantize, (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, - int num_rows)); + JSAMPARRAY input_buf, JSAMPARRAY output_buf, + int num_rows)); JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); JMETHOD(void, new_color_map, (j_decompress_ptr cinfo)); }; @@ -281,9 +281,9 @@ struct jpeg_color_quantizer { #ifdef RIGHT_SHIFT_IS_UNSIGNED #define SHIFT_TEMPS INT32 shift_temp; #define RIGHT_SHIFT(x,shft) \ - ((shift_temp = (x)) < 0 ? \ - (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ - (shift_temp >> (shft))) + ((shift_temp = (x)) < 0 ? \ + (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ + (shift_temp >> (shft))) #else #define SHIFT_TEMPS #define RIGHT_SHIFT(x,shft) ((x) >> (shft)) @@ -359,13 +359,13 @@ EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); /* Compression module initialization routines */ EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo, - boolean transcode_only)); + boolean transcode_only)); EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); + boolean need_full_buffer)); EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); + boolean need_full_buffer)); EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo, - boolean need_full_buffer)); + boolean need_full_buffer)); EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo)); EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo)); @@ -375,11 +375,11 @@ EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo)); /* Decompression module initialization routines */ EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); + boolean need_full_buffer)); EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); + boolean need_full_buffer)); EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo, - boolean need_full_buffer)); + boolean need_full_buffer)); EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo)); EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo)); @@ -397,10 +397,10 @@ EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo)); EXTERN(long) jdiv_round_up JPP((long a, long b)); EXTERN(long) jround_up JPP((long a, long b)); EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols)); + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols)); EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, - JDIMENSION num_blocks)); + JDIMENSION num_blocks)); /* Constant tables in jutils.c */ #if 0 /* This table is not actually needed in v6a */ extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */ diff --git a/3rdparty/libjpeg/jpeglib.h b/3rdparty/libjpeg/jpeglib.h index 3e58864fc3..939b50be58 100644 --- a/3rdparty/libjpeg/jpeglib.h +++ b/3rdparty/libjpeg/jpeglib.h @@ -2,7 +2,7 @@ * jpeglib.h * * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2002-2012 by Guido Vollbeding. + * Modified 2002-2015 by Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -39,12 +39,12 @@ extern "C" { #define JPEG_LIB_VERSION 90 /* Compatibility version 9.0 */ #define JPEG_LIB_VERSION_MAJOR 9 -#define JPEG_LIB_VERSION_MINOR 0 +#define JPEG_LIB_VERSION_MINOR 2 /* Various constants determining the sizes of things. - * All of these are specified by the JPEG standard, so don't change them - * if you want to be compatible. + * All of these are specified by the JPEG standard, + * so don't change them if you want to be compatible. */ #define DCTSIZE 8 /* The basic DCT block is 8x8 coefficients */ @@ -109,7 +109,7 @@ typedef struct { typedef struct { /* These two fields directly represent the contents of a JPEG DHT marker */ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ - /* length k bits; bits[0] is unused */ + /* length k bits; bits[0] is unused */ UINT8 huffval[256]; /* The symbols, in order of incr code length */ /* This field is used only during compression. It's initialized FALSE when * the table is created, and set TRUE when it's been output to the file. @@ -137,9 +137,9 @@ typedef struct { /* The decompressor output side may not use these variables. */ int dc_tbl_no; /* DC entropy table selector (0..3) */ int ac_tbl_no; /* AC entropy table selector (0..3) */ - + /* Remaining fields should be treated as private by applications. */ - + /* These values are computed during compression or decompression startup: */ /* Component's size in DCT blocks. * Any dummy blocks added to complete an MCU are not counted; therefore @@ -157,16 +157,21 @@ typedef struct { /* The downsampled dimensions are the component's actual, unpadded number * of samples at the main buffer (preprocessing/compression interface); * DCT scaling is included, so - * downsampled_width = ceil(image_width * Hi/Hmax * DCT_h_scaled_size/DCTSIZE) + * downsampled_width = + * ceil(image_width * Hi/Hmax * DCT_h_scaled_size/block_size) * and similarly for height. */ JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_height; /* actual height in samples */ - /* This flag is used only for decompression. In cases where some of the - * components will be ignored (eg grayscale output from YCbCr image), - * we can skip most computations for the unused components. + /* For decompression, in cases where some of the components will be + * ignored (eg grayscale output from YCbCr image), we can skip most + * computations for the unused components. + * For compression, some of the components will need further quantization + * scale by factor of 2 after DCT (eg BG_YCC output from normal RGB input). + * The field is first set TRUE for decompression, FALSE for compression + * in initial_setup, and then adapted in color conversion setup. */ - boolean component_needed; /* do we need the value of this component? */ + boolean component_needed; /* These values are computed before starting a scan of the component. */ /* The decompressor output side may not use these variables. */ @@ -213,27 +218,29 @@ struct jpeg_marker_struct { /* Known color spaces. */ typedef enum { - JCS_UNKNOWN, /* error/unspecified */ - JCS_GRAYSCALE, /* monochrome */ - JCS_RGB, /* red/green/blue */ - JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ - JCS_CMYK, /* C/M/Y/K */ - JCS_YCCK /* Y/Cb/Cr/K */ + JCS_UNKNOWN, /* error/unspecified */ + JCS_GRAYSCALE, /* monochrome */ + JCS_RGB, /* red/green/blue, standard RGB (sRGB) */ + JCS_YCbCr, /* Y/Cb/Cr (also known as YUV), standard YCC */ + JCS_CMYK, /* C/M/Y/K */ + JCS_YCCK, /* Y/Cb/Cr/K */ + JCS_BG_RGB, /* big gamut red/green/blue, bg-sRGB */ + JCS_BG_YCC /* big gamut Y/Cb/Cr, bg-sYCC */ } J_COLOR_SPACE; /* Supported color transforms. */ typedef enum { - JCT_NONE = 0, - JCT_SUBTRACT_GREEN = 1 + JCT_NONE = 0, + JCT_SUBTRACT_GREEN = 1 } J_COLOR_TRANSFORM; /* DCT/IDCT algorithm options. */ typedef enum { - JDCT_ISLOW, /* slow but accurate integer algorithm */ - JDCT_IFAST, /* faster, less accurate integer method */ - JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ + JDCT_ISLOW, /* slow but accurate integer algorithm */ + JDCT_IFAST, /* faster, less accurate integer method */ + JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ } J_DCT_METHOD; #ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ @@ -246,9 +253,9 @@ typedef enum { /* Dithering options for decompression. */ typedef enum { - JDITHER_NONE, /* no dithering */ - JDITHER_ORDERED, /* simple ordered dither */ - JDITHER_FS /* Floyd-Steinberg error diffusion dither */ + JDITHER_NONE, /* no dithering */ + JDITHER_ORDERED, /* simple ordered dither */ + JDITHER_FS /* Floyd-Steinberg error diffusion dither */ } J_DITHER_MODE; @@ -407,7 +414,7 @@ struct jpeg_compress_struct { * There are v_samp_factor * DCTSIZE sample rows of each component in an * "iMCU" (interleaved MCU) row. */ - + /* * These fields are valid during any one scan. * They describe the components and MCUs actually appearing in the scan. @@ -415,10 +422,10 @@ struct jpeg_compress_struct { int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ - + JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - + int blocks_in_MCU; /* # of DCT blocks per MCU */ int MCU_membership[C_MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ @@ -704,7 +711,7 @@ struct jpeg_error_mgr { #define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ /* Reset error state variables at start of a new image */ JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); - + /* The message ID code and any parameters are saved here. * A message can have one string parameter or up to 8 int parameters. */ @@ -714,11 +721,11 @@ struct jpeg_error_mgr { int i[8]; char s[JMSG_STR_PARM_MAX]; } msg_parm; - + /* Standard state variables for error facility */ - + int trace_level; /* max msg_level that will be displayed */ - + /* For recoverable corrupt-data errors, we emit a warning message, * but keep going unless emit_message chooses to abort. emit_message * should count warnings in num_warnings. The surrounding application @@ -808,38 +815,38 @@ typedef struct jvirt_barray_control * jvirt_barray_ptr; struct jpeg_memory_mgr { /* Method pointers */ JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); + size_t sizeofobject)); JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); + size_t sizeofobject)); JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, - JDIMENSION numrows)); + JDIMENSION samplesperrow, + JDIMENSION numrows)); JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, - JDIMENSION numrows)); + JDIMENSION blocksperrow, + JDIMENSION numrows)); JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION samplesperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); + int pool_id, + boolean pre_zero, + JDIMENSION samplesperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION blocksperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); + int pool_id, + boolean pre_zero, + JDIMENSION blocksperrow, + JDIMENSION numrows, + JDIMENSION maxaccess)); JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, - jvirt_sarray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); + jvirt_sarray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, - jvirt_barray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); + jvirt_barray_ptr ptr, + JDIMENSION start_row, + JDIMENSION num_rows, + boolean writable)); JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); JMETHOD(void, self_destruct, (j_common_ptr cinfo)); @@ -876,7 +883,7 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); /* Short forms of external names for systems with brain-damaged linkers. * We shorten external names to be unique in the first six letters, which * is good enough for all known systems. - * (If your compiler itself needs names to be unique in less than 15 + * (If your compiler itself needs names to be unique in less than 15 * characters, you are out of luck. Get a better compiler.) */ @@ -939,7 +946,7 @@ typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); /* Default error-management setup */ EXTERN(struct jpeg_error_mgr *) jpeg_std_error - JPP((struct jpeg_error_mgr * err)); + JPP((struct jpeg_error_mgr * err)); /* Initialization of JPEG compression objects. * jpeg_create_compress() and jpeg_create_decompress() are the exported @@ -950,14 +957,14 @@ EXTERN(struct jpeg_error_mgr *) jpeg_std_error */ #define jpeg_create_compress(cinfo) \ jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_compress_struct)) + (size_t) sizeof(struct jpeg_compress_struct)) #define jpeg_create_decompress(cinfo) \ jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_decompress_struct)) + (size_t) sizeof(struct jpeg_decompress_struct)) EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, - int version, size_t structsize)); + int version, size_t structsize)); EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, - int version, size_t structsize)); + int version, size_t structsize)); /* Destruction of JPEG compression objects */ EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); @@ -969,42 +976,42 @@ EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); /* Data source and destination managers: memory buffers. */ EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, - unsigned char ** outbuffer, - unsigned long * outsize)); + unsigned char ** outbuffer, + unsigned long * outsize)); EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, - unsigned char * inbuffer, - unsigned long insize)); + const unsigned char * inbuffer, + unsigned long insize)); /* Default parameter setup for compression */ EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); /* Compression parameter setup aids */ EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, - J_COLOR_SPACE colorspace)); + J_COLOR_SPACE colorspace)); EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, - boolean force_baseline)); + boolean force_baseline)); EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, - int scale_factor, - boolean force_baseline)); + int scale_factor, + boolean force_baseline)); EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo, - boolean force_baseline)); + boolean force_baseline)); EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, - boolean force_baseline)); + const unsigned int *basic_table, + int scale_factor, + boolean force_baseline)); EXTERN(int) jpeg_quality_scaling JPP((int quality)); EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, - boolean suppress)); + boolean suppress)); EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); /* Main entry points for compression */ EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, - boolean write_all_tables)); + boolean write_all_tables)); EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION num_lines)); + JSAMPARRAY scanlines, + JDIMENSION num_lines)); EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); /* Precalculate JPEG dimensions for current compression parameters. */ @@ -1012,25 +1019,25 @@ EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo)); /* Replaces jpeg_write_scanlines when writing raw downsampled data. */ EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION num_lines)); + JSAMPIMAGE data, + JDIMENSION num_lines)); /* Write a special marker. See libjpeg.txt concerning safe usage. */ EXTERN(void) jpeg_write_marker - JPP((j_compress_ptr cinfo, int marker, - const JOCTET * dataptr, unsigned int datalen)); + JPP((j_compress_ptr cinfo, int marker, + const JOCTET * dataptr, unsigned int datalen)); /* Same, but piecemeal. */ EXTERN(void) jpeg_write_m_header - JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); + JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); EXTERN(void) jpeg_write_m_byte - JPP((j_compress_ptr cinfo, int val)); + JPP((j_compress_ptr cinfo, int val)); /* Alternate compression function: just write an abbreviated table file */ EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); /* Decompression startup: read start of JPEG datastream to see what's there */ EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, - boolean require_image)); + boolean require_image)); /* Return value is one of: */ #define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ #define JPEG_HEADER_OK 1 /* Found valid image datastream */ @@ -1044,19 +1051,19 @@ EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, /* Main entry points for decompression */ EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION max_lines)); + JSAMPARRAY scanlines, + JDIMENSION max_lines)); EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); /* Replaces jpeg_read_scanlines when reading raw downsampled data. */ EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION max_lines)); + JSAMPIMAGE data, + JDIMENSION max_lines)); /* Additional entry points for buffered-image mode. */ EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, - int scan_number)); + int scan_number)); EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); @@ -1074,20 +1081,20 @@ EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); /* Control saving of COM and APPn markers into marker_list. */ EXTERN(void) jpeg_save_markers - JPP((j_decompress_ptr cinfo, int marker_code, - unsigned int length_limit)); + JPP((j_decompress_ptr cinfo, int marker_code, + unsigned int length_limit)); /* Install a special processing method for COM or APPn markers. */ EXTERN(void) jpeg_set_marker_processor - JPP((j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine)); + JPP((j_decompress_ptr cinfo, int marker_code, + jpeg_marker_parser_method routine)); /* Read or write raw DCT coefficients --- useful for lossless transcoding. */ EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays)); + jvirt_barray_ptr * coef_arrays)); EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, - j_compress_ptr dstinfo)); + j_compress_ptr dstinfo)); /* If you choose to abort compression or decompression before completing * jpeg_finish_(de)compress, then you need to clean up to release memory, @@ -1106,7 +1113,7 @@ EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); /* Default restart-marker-resync procedure for use by data source modules */ EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, - int desired)); + int desired)); /* These marker codes are exported since applications and data source modules diff --git a/3rdparty/libjpeg/jquant1.c b/3rdparty/libjpeg/jquant1.c index 8753a36328..9d11f70669 100644 --- a/3rdparty/libjpeg/jquant1.c +++ b/3rdparty/libjpeg/jquant1.c @@ -231,7 +231,7 @@ select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) temp = total_colors / Ncolors[j]; temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */ if (temp > (long) max_colors) - break; /* won't fit, done with this pass */ + break; /* won't fit, done with this pass */ Ncolors[j]++; /* OK, apply the increment */ total_colors = (int) temp; changed = TRUE; @@ -284,8 +284,8 @@ create_colormap (j_decompress_ptr cinfo) /* Report selected color counts */ if (cinfo->out_color_components == 3) TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, - total_colors, cquantize->Ncolors[0], - cquantize->Ncolors[1], cquantize->Ncolors[2]); + total_colors, cquantize->Ncolors[0], + cquantize->Ncolors[1], cquantize->Ncolors[2]); else TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); @@ -310,9 +310,9 @@ create_colormap (j_decompress_ptr cinfo) val = output_value(cinfo, i, j, nci-1); /* Fill in all colormap entries that have this value of this component */ for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { - /* fill in blksize entries beginning at ptr */ - for (k = 0; k < blksize; k++) - colormap[i][ptr+k] = (JSAMPLE) val; + /* fill in blksize entries beginning at ptr */ + for (k = 0; k < blksize; k++) + colormap[i][ptr+k] = (JSAMPLE) val; } } blkdist = blksize; /* blksize of this color is blkdist of next */ @@ -374,15 +374,15 @@ create_colorindex (j_decompress_ptr cinfo) k = largest_input_value(cinfo, i, 0, nci-1); for (j = 0; j <= MAXJSAMPLE; j++) { while (j > k) /* advance val if past boundary */ - k = largest_input_value(cinfo, i, ++val, nci-1); + k = largest_input_value(cinfo, i, ++val, nci-1); /* premultiply so that no multiplication needed in main processing */ indexptr[j] = (JSAMPLE) (val * blksize); } /* Pad at both ends if necessary */ if (pad) for (j = 1; j <= MAXJSAMPLE; j++) { - indexptr[-j] = indexptr[0]; - indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; + indexptr[-j] = indexptr[0]; + indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE]; } } } @@ -402,7 +402,7 @@ make_odither_array (j_decompress_ptr cinfo, int ncolors) odither = (ODITHER_MATRIX_PTR) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(ODITHER_MATRIX)); + SIZEOF(ODITHER_MATRIX)); /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). * Hence the dither value for the matrix cell with fill order f * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). @@ -412,7 +412,7 @@ make_odither_array (j_decompress_ptr cinfo, int ncolors) for (j = 0; j < ODITHER_SIZE; j++) { for (k = 0; k < ODITHER_SIZE; k++) { num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k]))) - * MAXJSAMPLE; + * MAXJSAMPLE; /* Ensure round towards zero despite C's lack of consistency * about rounding negative values in integer division... */ @@ -425,7 +425,7 @@ make_odither_array (j_decompress_ptr cinfo, int ncolors) /* * Create the ordered-dither tables. - * Components having the same number of representative colors may + * Components having the same number of representative colors may * share a dither table. */ @@ -441,8 +441,8 @@ create_odither_tables (j_decompress_ptr cinfo) odither = NULL; /* search for matching prior component */ for (j = 0; j < i; j++) { if (nci == cquantize->Ncolors[j]) { - odither = cquantize->odither[j]; - break; + odither = cquantize->odither[j]; + break; } } if (odither == NULL) /* need a new table? */ @@ -458,7 +458,7 @@ create_odither_tables (j_decompress_ptr cinfo) METHODDEF(void) color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) + JSAMPARRAY output_buf, int num_rows) /* General case, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; @@ -476,7 +476,7 @@ color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (col = width; col > 0; col--) { pixcode = 0; for (ci = 0; ci < nc; ci++) { - pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); + pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); } *ptrout++ = (JSAMPLE) pixcode; } @@ -486,7 +486,7 @@ color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, METHODDEF(void) color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) + JSAMPARRAY output_buf, int num_rows) /* Fast path for out_color_components==3, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; @@ -514,7 +514,7 @@ color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, METHODDEF(void) quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) + JSAMPARRAY output_buf, int num_rows) /* General case, with ordered dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; @@ -532,7 +532,7 @@ quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ FMEMZERO((void FAR *) output_buf[row], - (size_t) (width * SIZEOF(JSAMPLE))); + (size_t) (width * SIZEOF(JSAMPLE))); row_index = cquantize->row_index; for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; @@ -542,17 +542,17 @@ quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, col_index = 0; for (col = width; col > 0; col--) { - /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, - * select output value, accumulate into output code for this pixel. - * Range-limiting need not be done explicitly, as we have extended - * the colorindex table to produce the right answers for out-of-range - * inputs. The maximum dither is +- MAXJSAMPLE; this sets the - * required amount of padding. - */ - *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; - input_ptr += nc; - output_ptr++; - col_index = (col_index + 1) & ODITHER_MASK; + /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + * select output value, accumulate into output code for this pixel. + * Range-limiting need not be done explicitly, as we have extended + * the colorindex table to produce the right answers for out-of-range + * inputs. The maximum dither is +- MAXJSAMPLE; this sets the + * required amount of padding. + */ + *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; + input_ptr += nc; + output_ptr++; + col_index = (col_index + 1) & ODITHER_MASK; } } /* Advance row index for next row */ @@ -564,7 +564,7 @@ quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, METHODDEF(void) quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) + JSAMPARRAY output_buf, int num_rows) /* Fast path for out_color_components==3, with ordered dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; @@ -593,11 +593,11 @@ quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (col = width; col > 0; col--) { pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) + - dither0[col_index]]); + dither0[col_index]]); pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) + - dither1[col_index]]); + dither1[col_index]]); pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) + - dither2[col_index]]); + dither2[col_index]]); *output_ptr++ = (JSAMPLE) pixcode; col_index = (col_index + 1) & ODITHER_MASK; } @@ -609,7 +609,7 @@ quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, METHODDEF(void) quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) + JSAMPARRAY output_buf, int num_rows) /* General case, with Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; @@ -637,22 +637,22 @@ quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ FMEMZERO((void FAR *) output_buf[row], - (size_t) (width * SIZEOF(JSAMPLE))); + (size_t) (width * SIZEOF(JSAMPLE))); for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; output_ptr = output_buf[row]; if (cquantize->on_odd_row) { - /* work right to left in this row */ - input_ptr += (width-1) * nc; /* so point to rightmost pixel */ - output_ptr += width-1; - dir = -1; - dirnc = -nc; - errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ + /* work right to left in this row */ + input_ptr += (width-1) * nc; /* so point to rightmost pixel */ + output_ptr += width-1; + dir = -1; + dirnc = -nc; + errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ } else { - /* work left to right in this row */ - dir = 1; - dirnc = nc; - errorptr = cquantize->fserrors[ci]; /* => entry before first column */ + /* work left to right in this row */ + dir = 1; + dirnc = nc; + errorptr = cquantize->fserrors[ci]; /* => entry before first column */ } colorindex_ci = cquantize->colorindex[ci]; colormap_ci = cquantize->sv_colormap[ci]; @@ -662,47 +662,47 @@ quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, belowerr = bpreverr = 0; for (col = width; col > 0; col--) { - /* cur holds the error propagated from the previous pixel on the - * current line. Add the error propagated from the previous line - * to form the complete error correction term for this pixel, and - * round the error term (which is expressed * 16) to an integer. - * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct - * for either sign of the error value. - * Note: errorptr points to *previous* column's array entry. - */ - cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); - /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. - * The maximum error is +- MAXJSAMPLE; this sets the required size - * of the range_limit array. - */ - cur += GETJSAMPLE(*input_ptr); - cur = GETJSAMPLE(range_limit[cur]); - /* Select output value, accumulate into output code for this pixel */ - pixcode = GETJSAMPLE(colorindex_ci[cur]); - *output_ptr += (JSAMPLE) pixcode; - /* Compute actual representation error at this pixel */ - /* Note: we can do this even though we don't have the final */ - /* pixel code, because the colormap is orthogonal. */ - cur -= GETJSAMPLE(colormap_ci[pixcode]); - /* Compute error fractions to be propagated to adjacent pixels. - * Add these into the running sums, and simultaneously shift the - * next-line error sums left by 1 column. - */ - bnexterr = cur; - delta = cur * 2; - cur += delta; /* form error * 3 */ - errorptr[0] = (FSERROR) (bpreverr + cur); - cur += delta; /* form error * 5 */ - bpreverr = belowerr + cur; - belowerr = bnexterr; - cur += delta; /* form error * 7 */ - /* At this point cur contains the 7/16 error value to be propagated - * to the next pixel on the current line, and all the errors for the - * next line have been shifted over. We are therefore ready to move on. - */ - input_ptr += dirnc; /* advance input ptr to next column */ - output_ptr += dir; /* advance output ptr to next column */ - errorptr += dir; /* advance errorptr to current column */ + /* cur holds the error propagated from the previous pixel on the + * current line. Add the error propagated from the previous line + * to form the complete error correction term for this pixel, and + * round the error term (which is expressed * 16) to an integer. + * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + * for either sign of the error value. + * Note: errorptr points to *previous* column's array entry. + */ + cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); + /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + * The maximum error is +- MAXJSAMPLE; this sets the required size + * of the range_limit array. + */ + cur += GETJSAMPLE(*input_ptr); + cur = GETJSAMPLE(range_limit[cur]); + /* Select output value, accumulate into output code for this pixel */ + pixcode = GETJSAMPLE(colorindex_ci[cur]); + *output_ptr += (JSAMPLE) pixcode; + /* Compute actual representation error at this pixel */ + /* Note: we can do this even though we don't have the final */ + /* pixel code, because the colormap is orthogonal. */ + cur -= GETJSAMPLE(colormap_ci[pixcode]); + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. + */ + bnexterr = cur; + delta = cur * 2; + cur += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr + cur); + cur += delta; /* form error * 5 */ + bpreverr = belowerr + cur; + belowerr = bnexterr; + cur += delta; /* form error * 7 */ + /* At this point cur contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + input_ptr += dirnc; /* advance input ptr to next column */ + output_ptr += dir; /* advance output ptr to next column */ + errorptr += dir; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error value into the * final fserrors[] entry. Note we need not unload belowerr because @@ -825,7 +825,7 @@ jinit_1pass_quantizer (j_decompress_ptr cinfo) cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_cquantizer)); + SIZEOF(my_cquantizer)); cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; cquantize->pub.start_pass = start_pass_1_quant; cquantize->pub.finish_pass = finish_pass_1_quant; diff --git a/3rdparty/libjpeg/jquant2.c b/3rdparty/libjpeg/jquant2.c index 2ac3f841b7..38fc2af7a5 100644 --- a/3rdparty/libjpeg/jquant2.c +++ b/3rdparty/libjpeg/jquant2.c @@ -42,7 +42,7 @@ * color space, and repeatedly splits the "largest" remaining box until we * have as many boxes as desired colors. Then the mean color in each * remaining box becomes one of the possible output colors. - * + * * The second pass over the image maps each input pixel to the closest output * color (optionally after applying a Floyd-Steinberg dithering correction). * This mapping is logically trivial, but making it go fast enough requires @@ -223,7 +223,7 @@ typedef my_cquantizer * my_cquantize_ptr; METHODDEF(void) prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, - JSAMPARRAY output_buf, int num_rows) + JSAMPARRAY output_buf, int num_rows) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register JSAMPROW ptr; @@ -238,11 +238,11 @@ prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, for (col = width; col > 0; col--) { /* get pixel value and index into the histogram */ histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT] - [GETJSAMPLE(ptr[1]) >> C1_SHIFT] - [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; + [GETJSAMPLE(ptr[1]) >> C1_SHIFT] + [GETJSAMPLE(ptr[2]) >> C2_SHIFT]; /* increment, check for overflow and undo increment if so. */ if (++(*histp) <= 0) - (*histp)--; + (*histp)--; ptr += 3; } } @@ -265,9 +265,9 @@ typedef struct { INT32 volume; /* The number of nonzero histogram cells within this box */ long colorcount; -} _box; +} box; -typedef _box * boxptr; +typedef box * boxptr; LOCAL(boxptr) @@ -279,7 +279,7 @@ find_biggest_color_pop (boxptr boxlist, int numboxes) register int i; register long maxc = 0; boxptr which = NULL; - + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->colorcount > maxc && boxp->volume > 0) { which = boxp; @@ -299,7 +299,7 @@ find_biggest_volume (boxptr boxlist, int numboxes) register int i; register INT32 maxv = 0; boxptr which = NULL; - + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->volume > maxv) { which = boxp; @@ -322,75 +322,75 @@ update_box (j_decompress_ptr cinfo, boxptr boxp) int c0min,c0max,c1min,c1max,c2min,c2max; INT32 dist0,dist1,dist2; long ccount; - + c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; - + if (c0max > c0min) for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c0min = c0min = c0; - goto have_c0min; - } + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } } have_c0min: if (c0max > c0min) for (c0 = c0max; c0 >= c0min; c0--) for (c1 = c1min; c1 <= c1max; c1++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c0max = c0max = c0; - goto have_c0max; - } + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } } have_c0max: if (c1max > c1min) for (c1 = c1min; c1 <= c1max; c1++) for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c1min = c1min = c1; - goto have_c1min; - } + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } } have_c1min: if (c1max > c1min) for (c1 = c1max; c1 >= c1min; c1--) for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1][c2min]; - for (c2 = c2min; c2 <= c2max; c2++) - if (*histp++ != 0) { - boxp->c1max = c1max = c1; - goto have_c1max; - } + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } } have_c1max: if (c2max > c2min) for (c2 = c2min; c2 <= c2max; c2++) for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1min][c2]; - for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) - if (*histp != 0) { - boxp->c2min = c2min = c2; - goto have_c2min; - } + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } } have_c2min: if (c2max > c2min) for (c2 = c2max; c2 >= c2min; c2--) for (c0 = c0min; c0 <= c0max; c0++) { - histp = & histogram[c0][c1min][c2]; - for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) - if (*histp != 0) { - boxp->c2max = c2max = c2; - goto have_c2max; - } + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } } have_c2max: @@ -406,16 +406,16 @@ update_box (j_decompress_ptr cinfo, boxptr boxp) dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; - + /* Now scan remaining volume of box and compute population */ ccount = 0; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++, histp++) - if (*histp != 0) { - ccount++; - } + if (*histp != 0) { + ccount++; + } } boxp->colorcount = ccount; } @@ -423,7 +423,7 @@ update_box (j_decompress_ptr cinfo, boxptr boxp) LOCAL(int) median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, - int desired_colors) + int desired_colors) /* Repeatedly select and split the largest box until we have enough boxes */ { int n,lb; @@ -512,24 +512,24 @@ compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) long c0total = 0; long c1total = 0; long c2total = 0; - + c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; - + for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) { - if ((count = *histp++) != 0) { - total += count; - c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; - c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; - c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; - } + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; + } } } - + cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); @@ -546,7 +546,7 @@ select_colors (j_decompress_ptr cinfo, int desired_colors) /* Allocate workspace for box list */ boxlist = (boxptr) (*cinfo->mem->alloc_small) - ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(_box)); + ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box)); /* Initialize one box containing whole space */ numboxes = 1; boxlist[0].c0min = 0; @@ -645,7 +645,7 @@ select_colors (j_decompress_ptr cinfo, int desired_colors) LOCAL(int) find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, - JSAMPLE colorlist[]) + JSAMPLE colorlist[]) /* Locate the colormap entries close enough to an update box to be candidates * for the nearest entry to some cell(s) in the update box. The update box * is specified by the center coordinates of its first cell. The number of @@ -702,11 +702,11 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, /* within cell range so no contribution to min_dist */ min_dist = 0; if (x <= centerc0) { - tdist = (x - maxc0) * C0_SCALE; - max_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; } else { - tdist = (x - minc0) * C0_SCALE; - max_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; } } @@ -724,11 +724,11 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, } else { /* within cell range so no contribution to min_dist */ if (x <= centerc1) { - tdist = (x - maxc1) * C1_SCALE; - max_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; } else { - tdist = (x - minc1) * C1_SCALE; - max_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; } } @@ -746,11 +746,11 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, } else { /* within cell range so no contribution to min_dist */ if (x <= centerc2) { - tdist = (x - maxc2) * C2_SCALE; - max_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; } else { - tdist = (x - minc2) * C2_SCALE; - max_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; } } @@ -774,7 +774,7 @@ find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, LOCAL(void) find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, - int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) + int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) /* Find the closest colormap entry for each cell in the update box, * given the list of candidate colors prepared by find_nearby_colors. * Return the indexes of the closest entries in the bestcolor[] array. @@ -798,17 +798,17 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, bptr = bestdist; for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) *bptr++ = 0x7FFFFFFFL; - + /* For each color selected by find_nearby_colors, * compute its distance to the center of each cell in the box. * If that's less than best-so-far, update best distance and color number. */ - + /* Nominal steps between cell centers ("x" in Thomas article) */ #define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) #define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) #define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) - + for (i = 0; i < numcolors; i++) { icolor = GETJSAMPLE(colorlist[i]); /* Compute (square of) distance from minc0/c1/c2 to this color */ @@ -830,20 +830,20 @@ find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, dist1 = dist0; xx1 = inc1; for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { - dist2 = dist1; - xx2 = inc2; - for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { - if (dist2 < *bptr) { - *bptr = dist2; - *cptr = (JSAMPLE) icolor; - } - dist2 += xx2; - xx2 += 2 * STEP_C2 * STEP_C2; - bptr++; - cptr++; - } - dist1 += xx1; - xx1 += 2 * STEP_C1 * STEP_C1; + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; } dist0 += xx0; xx0 += 2 * STEP_C0 * STEP_C0; @@ -882,7 +882,7 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); - + /* Determine which colormap entries are close enough to be candidates * for the nearest entry to some cell in the update box. */ @@ -890,7 +890,7 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) /* Determine the actually nearest colors. */ find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, - bestcolor); + bestcolor); /* Save the best color numbers (plus 1) in the main cache array */ c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ @@ -901,7 +901,7 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { cachep = & histogram[c0+ic0][c1+ic1][c2]; for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { - *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); + *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); } } } @@ -914,7 +914,7 @@ fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) METHODDEF(void) pass2_no_dither (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; @@ -938,7 +938,7 @@ pass2_no_dither (j_decompress_ptr cinfo, /* If we have not seen this color before, find nearest colormap entry */ /* and update the cache */ if (*cachep == 0) - fill_inverse_cmap(cinfo, c0,c1,c2); + fill_inverse_cmap(cinfo, c0,c1,c2); /* Now emit the colormap index for this cell */ *outptr++ = (JSAMPLE) (*cachep - 1); } @@ -948,7 +948,7 @@ pass2_no_dither (j_decompress_ptr cinfo, METHODDEF(void) pass2_fs_dither (j_decompress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) + JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; @@ -1029,14 +1029,14 @@ pass2_fs_dither (j_decompress_ptr cinfo, /* If we have not seen this color before, find nearest colormap */ /* entry and update the cache */ if (*cachep == 0) - fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); + fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT); /* Now emit the colormap index for this cell */ { register int pixcode = *cachep - 1; - *outptr = (JSAMPLE) pixcode; - /* Compute representation error for this pixel */ - cur0 -= GETJSAMPLE(colormap0[pixcode]); - cur1 -= GETJSAMPLE(colormap1[pixcode]); - cur2 -= GETJSAMPLE(colormap2[pixcode]); + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= GETJSAMPLE(colormap0[pixcode]); + cur1 -= GETJSAMPLE(colormap1[pixcode]); + cur2 -= GETJSAMPLE(colormap2[pixcode]); } /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the @@ -1044,30 +1044,30 @@ pass2_fs_dither (j_decompress_ptr cinfo, */ { register LOCFSERROR bnexterr, delta; - bnexterr = cur0; /* Process component 0 */ - delta = cur0 * 2; - cur0 += delta; /* form error * 3 */ - errorptr[0] = (FSERROR) (bpreverr0 + cur0); - cur0 += delta; /* form error * 5 */ - bpreverr0 = belowerr0 + cur0; - belowerr0 = bnexterr; - cur0 += delta; /* form error * 7 */ - bnexterr = cur1; /* Process component 1 */ - delta = cur1 * 2; - cur1 += delta; /* form error * 3 */ - errorptr[1] = (FSERROR) (bpreverr1 + cur1); - cur1 += delta; /* form error * 5 */ - bpreverr1 = belowerr1 + cur1; - belowerr1 = bnexterr; - cur1 += delta; /* form error * 7 */ - bnexterr = cur2; /* Process component 2 */ - delta = cur2 * 2; - cur2 += delta; /* form error * 3 */ - errorptr[2] = (FSERROR) (bpreverr2 + cur2); - cur2 += delta; /* form error * 5 */ - bpreverr2 = belowerr2 + cur2; - belowerr2 = bnexterr; - cur2 += delta; /* form error * 7 */ + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ } /* At this point curN contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the @@ -1198,16 +1198,16 @@ start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) if (cinfo->dither_mode == JDITHER_FS) { size_t arraysize = (size_t) ((cinfo->output_width + 2) * - (3 * SIZEOF(FSERROR))); + (3 * SIZEOF(FSERROR))); /* Allocate Floyd-Steinberg workspace if we didn't already. */ if (cquantize->fserrors == NULL) - cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) - ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); + cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) + ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); /* Initialize the propagated errors to zero. */ FMEMZERO((void FAR *) cquantize->fserrors, arraysize); /* Make the error-limit table if we didn't already. */ if (cquantize->error_limiter == NULL) - init_error_limit(cinfo); + init_error_limit(cinfo); cquantize->on_odd_row = FALSE; } @@ -1216,7 +1216,7 @@ start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan) if (cquantize->needs_zeroed) { for (i = 0; i < HIST_C0_ELEMS; i++) { FMEMZERO((void FAR *) histogram[i], - HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); } cquantize->needs_zeroed = FALSE; } @@ -1249,7 +1249,7 @@ jinit_2pass_quantizer (j_decompress_ptr cinfo) cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - SIZEOF(my_cquantizer)); + SIZEOF(my_cquantizer)); cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; cquantize->pub.start_pass = start_pass_2_quant; cquantize->pub.new_color_map = new_color_map_2_quant; diff --git a/3rdparty/libjpeg/jutils.c b/3rdparty/libjpeg/jutils.c index 49a8ce2eab..5b16b6d03c 100644 --- a/3rdparty/libjpeg/jutils.c +++ b/3rdparty/libjpeg/jutils.c @@ -175,8 +175,8 @@ jzero_far (void FAR * target, size_t bytestozero) GLOBAL(void) jcopy_sample_rows (JSAMPARRAY input_array, int source_row, - JSAMPARRAY output_array, int dest_row, - int num_rows, JDIMENSION num_cols) + JSAMPARRAY output_array, int dest_row, + int num_rows, JDIMENSION num_cols) /* Copy some rows of samples from one place to another. * num_rows rows are copied from input_array[source_row++] * to output_array[dest_row++]; these areas may overlap for duplication. @@ -209,7 +209,7 @@ jcopy_sample_rows (JSAMPARRAY input_array, int source_row, GLOBAL(void) jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, - JDIMENSION num_blocks) + JDIMENSION num_blocks) /* Copy a row of coefficient blocks from one place to another. */ { #ifdef FMEMCOPY diff --git a/3rdparty/libjpeg/jversion.h b/3rdparty/libjpeg/jversion.h index 232085f13b..0740b317d7 100644 --- a/3rdparty/libjpeg/jversion.h +++ b/3rdparty/libjpeg/jversion.h @@ -1,7 +1,7 @@ /* * jversion.h * - * Copyright (C) 1991-2013, Thomas G. Lane, Guido Vollbeding. + * Copyright (C) 1991-2016, Thomas G. Lane, Guido Vollbeding. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * @@ -9,6 +9,6 @@ */ -#define JVERSION "9 13-Jan-2013" +#define JVERSION "9b 17-Jan-2016" -#define JCOPYRIGHT "Copyright (C) 2013, Thomas G. Lane, Guido Vollbeding" +#define JCOPYRIGHT "Copyright (C) 2016, Thomas G. Lane, Guido Vollbeding" From a9de6900e5141f829cfa74e76b062daebf8542a4 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 7 Dec 2017 18:30:33 +0300 Subject: [PATCH 5/8] cmake(3rdparty): BUILD_ options before WITH_ options --- CMakeLists.txt | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cb9db922d..058e1a7419 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,6 +187,17 @@ endif() OCV_OPTION(OPENCV_ENABLE_NONFREE "Enable non-free algorithms" OFF) +# 3rd party libs +OCV_OPTION(BUILD_ZLIB "Build zlib from source" WIN32 OR APPLE) +OCV_OPTION(BUILD_TIFF "Build libtiff from source" WIN32 OR ANDROID OR APPLE) +OCV_OPTION(BUILD_JASPER "Build libjasper from source" WIN32 OR ANDROID OR APPLE) +OCV_OPTION(BUILD_JPEG "Build libjpeg from source" WIN32 OR ANDROID OR APPLE) +OCV_OPTION(BUILD_PNG "Build libpng from source" WIN32 OR ANDROID OR APPLE) +OCV_OPTION(BUILD_OPENEXR "Build openexr from source" (WIN32 OR ANDROID OR APPLE) AND NOT WINRT) +OCV_OPTION(BUILD_TBB "Download and build TBB from source" ANDROID ) +OCV_OPTION(BUILD_IPP_IW "Build IPP IW from source" NOT MINGW IF (X86_64 OR X86) AND NOT WINRT ) +OCV_OPTION(BUILD_ITT "Build Intel ITT from source" NOT MINGW IF (X86_64 OR X86) AND NOT WINRT AND NOT APPLE_FRAMEWORK ) + # Optional 3rd party components # =================================================== OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON IF (NOT ANDROID AND NOT IOS AND NOT WINRT) ) @@ -272,18 +283,6 @@ OCV_OPTION(BUILD_ANDROID_SERVICE "Build OpenCV Manager for Google Play" OFF I OCV_OPTION(BUILD_CUDA_STUBS "Build CUDA modules stubs when no CUDA SDK" OFF IF (NOT APPLE_FRAMEWORK) ) OCV_OPTION(BUILD_JAVA "Enable Java support" (ANDROID OR NOT CMAKE_CROSSCOMPILING) IF (ANDROID OR (NOT APPLE_FRAMEWORK AND NOT WINRT)) ) - -# 3rd party libs -OCV_OPTION(BUILD_ZLIB "Build zlib from source" WIN32 OR APPLE ) -OCV_OPTION(BUILD_TIFF "Build libtiff from source" WIN32 OR ANDROID OR APPLE ) -OCV_OPTION(BUILD_JASPER "Build libjasper from source" WIN32 OR ANDROID OR APPLE ) -OCV_OPTION(BUILD_JPEG "Build libjpeg from source" WIN32 OR ANDROID OR APPLE ) -OCV_OPTION(BUILD_PNG "Build libpng from source" WIN32 OR ANDROID OR APPLE ) -OCV_OPTION(BUILD_OPENEXR "Build openexr from source" (WIN32 OR ANDROID OR APPLE) AND NOT WINRT) -OCV_OPTION(BUILD_TBB "Download and build TBB from source" ANDROID ) -OCV_OPTION(BUILD_IPP_IW "Build IPP IW from source" NOT MINGW IF (X86_64 OR X86) AND NOT WINRT ) -OCV_OPTION(BUILD_ITT "Build Intel ITT from source" NOT MINGW IF (X86_64 OR X86) AND NOT WINRT AND NOT APPLE_FRAMEWORK ) - # OpenCV installation options # =================================================== OCV_OPTION(INSTALL_CREATE_DISTRIB "Change install rules to build the distribution package" OFF ) From ae5e1f8eceebeb51365660cb5290becf864e3b45 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 8 Dec 2017 18:47:47 +0300 Subject: [PATCH 6/8] 3rdparty: eliminate jasper build warning --- 3rdparty/libjasper/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/3rdparty/libjasper/CMakeLists.txt b/3rdparty/libjasper/CMakeLists.txt index 01bab32e66..617e11d70d 100644 --- a/3rdparty/libjasper/CMakeLists.txt +++ b/3rdparty/libjasper/CMakeLists.txt @@ -25,7 +25,9 @@ endif(WIN32 AND NOT MINGW) ocv_warnings_disable(CMAKE_C_FLAGS -Wno-implicit-function-declaration -Wno-uninitialized -Wmissing-prototypes -Wno-unused-but-set-parameter -Wmissing-declarations -Wunused -Wshadow - -Wsign-compare -Wstrict-overflow -Wpointer-compare) + -Wsign-compare -Wstrict-overflow -Wpointer-compare + -Wabsolute-value # clang on Linux +) ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter -Wstrict-prototypes) # clang ocv_warnings_disable(CMAKE_C_FLAGS /wd4013 /wd4018 /wd4101 /wd4244 /wd4267 /wd4715) # vs2005 From 5c709f4aaa2bbf3c7df8070e0b323134fd6845e7 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 8 Dec 2017 15:47:54 +0300 Subject: [PATCH 7/8] 3rdparty: update libtiff 4.0.9 --- 3rdparty/libtiff/CMakeLists.txt | 372 +- 3rdparty/libtiff/tif_aux.c | 492 +- 3rdparty/libtiff/tif_close.c | 98 +- 3rdparty/libtiff/tif_codec.c | 68 +- 3rdparty/libtiff/tif_color.c | 272 +- 3rdparty/libtiff/tif_compress.c | 312 +- 3rdparty/libtiff/tif_config.h.cmake.in | 261 + 3rdparty/libtiff/tif_config.h.cmakein | 162 - 3rdparty/libtiff/tif_dir.c | 2726 +++---- 3rdparty/libtiff/tif_dir.h | 277 +- 3rdparty/libtiff/tif_dirinfo.c | 1537 ++-- 3rdparty/libtiff/tif_dirread.c | 9903 ++++++++++++------------ 3rdparty/libtiff/tif_dirwrite.c | 3734 ++++----- 3rdparty/libtiff/tif_dumpmode.c | 136 +- 3rdparty/libtiff/tif_error.c | 66 +- 3rdparty/libtiff/tif_extension.c | 58 +- 3rdparty/libtiff/tif_fax3.c | 2055 ++--- 3rdparty/libtiff/tif_fax3.h | 490 +- 3rdparty/libtiff/tif_flush.c | 64 +- 3rdparty/libtiff/tif_getimage.c | 3465 +++++---- 3rdparty/libtiff/tif_jbig.c | 225 +- 3rdparty/libtiff/tif_jpeg.c | 3068 ++++---- 3rdparty/libtiff/tif_jpeg_12.c | 6 +- 3rdparty/libtiff/tif_luv.c | 2232 +++--- 3rdparty/libtiff/tif_lzma.c | 624 +- 3rdparty/libtiff/tif_lzw.c | 1711 ++-- 3rdparty/libtiff/tif_next.c | 239 +- 3rdparty/libtiff/tif_ojpeg.c | 3775 ++++----- 3rdparty/libtiff/tif_open.c | 922 +-- 3rdparty/libtiff/tif_packbits.c | 441 +- 3rdparty/libtiff/tif_pixarlog.c | 1957 ++--- 3rdparty/libtiff/tif_predict.c | 1097 +-- 3rdparty/libtiff/tif_predict.h | 36 +- 3rdparty/libtiff/tif_print.c | 1160 +-- 3rdparty/libtiff/tif_read.c | 1787 +++-- 3rdparty/libtiff/tif_strip.c | 458 +- 3rdparty/libtiff/tif_swab.c | 314 +- 3rdparty/libtiff/tif_thunder.c | 211 +- 3rdparty/libtiff/tif_tile.c | 393 +- 3rdparty/libtiff/tif_unix.c | 308 +- 3rdparty/libtiff/tif_version.c | 18 +- 3rdparty/libtiff/tif_warning.c | 66 +- 3rdparty/libtiff/tif_win32.c | 530 +- 3rdparty/libtiff/tif_write.c | 1029 +-- 3rdparty/libtiff/tif_zip.c | 561 +- 3rdparty/libtiff/tiff.h | 203 +- 3rdparty/libtiff/tiffconf.h.cmake.in | 130 + 3rdparty/libtiff/tiffio.h | 186 +- 3rdparty/libtiff/tiffio.hxx | 16 +- 3rdparty/libtiff/tiffiop.h | 336 +- 3rdparty/libtiff/tiffvers.h | 4 +- 3rdparty/libtiff/uvcode.h | 332 +- cmake/OpenCVFindLibsGrfmt.cmake | 44 +- 53 files changed, 26997 insertions(+), 23970 deletions(-) create mode 100644 3rdparty/libtiff/tif_config.h.cmake.in delete mode 100644 3rdparty/libtiff/tif_config.h.cmakein create mode 100644 3rdparty/libtiff/tiffconf.h.cmake.in diff --git a/3rdparty/libtiff/CMakeLists.txt b/3rdparty/libtiff/CMakeLists.txt index 67ceac9e3f..11ae3df3ab 100644 --- a/3rdparty/libtiff/CMakeLists.txt +++ b/3rdparty/libtiff/CMakeLists.txt @@ -4,27 +4,372 @@ # ---------------------------------------------------------------------------- project(${TIFF_LIBRARY}) +include(CheckCSourceCompiles) include(CheckFunctionExists) include(CheckIncludeFile) -check_include_file(assert.h HAVE_ASSERT_H) -check_include_file(fcntl.h HAVE_FCNTL_H) -check_include_file(io.h HAVE_IO_H) -check_function_exists(jbg_newlen HAVE_JBG_NEWLEN) -check_include_file(search.h HAVE_SEARCH_H) -check_include_file(string.h HAVE_STRING_H) + +# Find libm, if available +find_library(M_LIBRARY m) + +check_include_file(assert.h HAVE_ASSERT_H) +if(NOT MSVC) + check_include_file(dlfcn.h HAVE_DLFCN_H) +endif() +check_include_file(fcntl.h HAVE_FCNTL_H) +check_include_file(inttypes.h HAVE_INTTYPES_H) +check_include_file(io.h HAVE_IO_H) +check_include_file(limits.h HAVE_LIMITS_H) +check_include_file(malloc.h HAVE_MALLOC_H) +check_include_file(memory.h HAVE_MEMORY_H) +check_include_file(search.h HAVE_SEARCH_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(string.h HAVE_STRING_H) +if(NOT MSVC) + check_include_file(strings.h HAVE_STRINGS_H) + check_include_file(sys/time.h HAVE_SYS_TIME_H) +endif() check_include_file(sys/types.h HAVE_SYS_TYPES_H) if(NOT MSVC) - check_include_file(unistd.h HAVE_UNISTD_H) - check_function_exists(mmap HAVE_MMAP) + check_include_file(unistd.h HAVE_UNISTD_H) endif() +if(MSVC) + set(INLINE_KEYWORD "inline") +else() + # Inspired from /usr/share/autoconf/autoconf/c.m4 + foreach(inline_keyword "inline" "__inline__" "__inline") + if(NOT DEFINED C_INLINE) + set(CMAKE_REQUIRED_DEFINITIONS_SAVE ${CMAKE_REQUIRED_DEFINITIONS}) + set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + "-Dinline=${inline_keyword}") + check_c_source_compiles(" + typedef int foo_t; + static inline foo_t static_foo() {return 0;} + foo_t foo(){return 0;} + int main(int argc, char *argv[]) {return 0;}" + C_HAS_${inline_keyword}) + set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS_SAVE}) + if(C_HAS_${inline_keyword}) + set(C_INLINE TRUE) + set(INLINE_KEYWORD "${inline_keyword}") + endif() + endif() + endforeach() + if(NOT DEFINED C_INLINE) + set(INLINE_KEYWORD) + endif() +endif() + + +# Check type sizes +# NOTE: Could be replaced with C99 +check_type_size("signed short" SIZEOF_SIGNED_SHORT) +check_type_size("unsigned short" SIZEOF_UNSIGNED_SHORT) +check_type_size("signed int" SIZEOF_SIGNED_INT) +check_type_size("unsigned int" SIZEOF_UNSIGNED_INT) +check_type_size("signed long" SIZEOF_SIGNED_LONG) +check_type_size("unsigned long" SIZEOF_UNSIGNED_LONG) +check_type_size("signed long long" SIZEOF_SIGNED_LONG_LONG) +check_type_size("unsigned long long" SIZEOF_UNSIGNED_LONG_LONG) +check_type_size("unsigned char *" SIZEOF_UNSIGNED_CHAR_P) + +set(CMAKE_EXTRA_INCLUDE_FILES_SAVE ${CMAKE_EXTRA_INCLUDE_FILES}) +set(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES} "stddef.h") +check_type_size("size_t" SIZEOF_SIZE_T) +check_type_size("ptrdiff_t" SIZEOF_PTRDIFF_T) +set(CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES_SAVE}) + +set(TIFF_INT8_T "signed char") +set(TIFF_UINT8_T "unsigned char") + +set(TIFF_INT16_T "signed short") +set(TIFF_UINT16_T "unsigned short") + +if(SIZEOF_SIGNED_INT EQUAL 4) + set(TIFF_INT32_T "signed int") + set(TIFF_INT32_FORMAT "%d") +elseif(SIZEOF_SIGNED_LONG EQUAL 4) + set(TIFF_INT32_T "signed long") + set(TIFF_INT32_FORMAT "%ld") +endif() + +if(SIZEOF_UNSIGNED_INT EQUAL 4) + set(TIFF_UINT32_T "unsigned int") + set(TIFF_UINT32_FORMAT "%u") +elseif(SIZEOF_UNSIGNED_LONG EQUAL 4) + set(TIFF_UINT32_T "unsigned long") + set(TIFF_UINT32_FORMAT "%lu") +endif() + +if(SIZEOF_SIGNED_LONG EQUAL 8) + set(TIFF_INT64_T "signed long") + set(TIFF_INT64_FORMAT "%ld") +elseif(SIZEOF_SIGNED_LONG_LONG EQUAL 8) + set(TIFF_INT64_T "signed long long") + if(MINGW) + set(TIFF_INT64_FORMAT "%I64d") + else() + set(TIFF_INT64_FORMAT "%lld") + endif() +endif() + +if(SIZEOF_UNSIGNED_LONG EQUAL 8) + set(TIFF_UINT64_T "unsigned long") + set(TIFF_UINT64_FORMAT "%lu") +elseif(SIZEOF_UNSIGNED_LONG_LONG EQUAL 8) + set(TIFF_UINT64_T "unsigned long long") + if(MINGW) + set(TIFF_UINT64_FORMAT "%I64u") + else() + set(TIFF_UINT64_FORMAT "%llu") + endif() +endif() + +if(SIZEOF_UNSIGNED_INT EQUAL SIZEOF_SIZE_T) + set(TIFF_SIZE_T "unsigned int") + set(TIFF_SIZE_FORMAT "%u") +elseif(SIZEOF_UNSIGNED_LONG EQUAL SIZEOF_SIZE_T) + set(TIFF_SIZE_T "unsigned long") + set(TIFF_SIZE_FORMAT "%lu") +elseif(SIZEOF_UNSIGNED_LONG_LONG EQUAL SIZEOF_SIZE_T) + set(TIFF_SIZE_T "unsigned long") + if(MINGW) + set(TIFF_SIZE_FORMAT "%I64u") + else() + set(TIFF_SIZE_FORMAT "%llu") + endif() +endif() + +if(SIZEOF_SIGNED_INT EQUAL SIZEOF_UNSIGNED_CHAR_P) + set(TIFF_SSIZE_T "signed int") + set(TIFF_SSIZE_FORMAT "%d") +elseif(SIZEOF_SIGNED_LONG EQUAL SIZEOF_UNSIGNED_CHAR_P) + set(TIFF_SSIZE_T "signed long") + set(TIFF_SSIZE_FORMAT "%ld") +elseif(SIZEOF_SIGNED_LONG_LONG EQUAL SIZEOF_UNSIGNED_CHAR_P) + set(TIFF_SSIZE_T "signed long long") + if(MINGW) + set(TIFF_SSIZE_FORMAT "%I64d") + else() + set(TIFF_SSIZE_FORMAT "%lld") + endif() +endif() + +if(NOT SIZEOF_PTRDIFF_T) + set(TIFF_PTRDIFF_T "${TIFF_SSIZE_T}") + set(TIFF_PTRDIFF_FORMAT "${SSIZE_FORMAT}") +else() + set(TIFF_PTRDIFF_T "ptrdiff_t") + set(TIFF_PTRDIFF_FORMAT "%ld") +endif() + +# Nonstandard int types +if(NOT MSVC) + check_type_size(INT8 int8) + set(HAVE_INT8 ${INT8}) + check_type_size(INT16 int16) + set(HAVE_INT16 ${INT16}) + check_type_size(INT32 int32) + set(HAVE_INT32 ${INT32}) +endif() + +# Check functions +if(NOT MSVC) + set(CMAKE_REQUIRED_LIBRARIES_SAVE ${CMAKE_REQUIRED_LIBRARIES}) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${M_LIBRARY}) + check_function_exists(floor HAVE_FLOOR) + check_function_exists(pow HAVE_POW) + check_function_exists(sqrt HAVE_SQRT) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES_SAVE}) +endif() + +if(NOT MSVC) + check_function_exists(isascii HAVE_ISASCII) + check_function_exists(memset HAVE_MEMSET) + check_function_exists(mmap HAVE_MMAP) + check_function_exists(getopt HAVE_GETOPT) +endif() +check_function_exists(memmove HAVE_MEMMOVE) +check_function_exists(setmode HAVE_SETMODE) +check_function_exists(strcasecmp HAVE_STRCASECMP) +check_function_exists(strchr HAVE_STRCHR) +check_function_exists(strrchr HAVE_STRRCHR) +check_function_exists(strstr HAVE_STRSTR) +check_function_exists(strtol HAVE_STRTOL) +check_function_exists(strtol HAVE_STRTOUL) +check_function_exists(strtoull HAVE_STRTOULL) +check_function_exists(lfind HAVE_LFIND) + +# May be inlined, so check it compiles: +check_c_source_compiles(" +#include +int main(void) { + char buf[10]; + snprintf(buf, 10, \"Test %d\", 1); + return 0; +}" + HAVE_SNPRINTF) + +if(NOT HAVE_SNPRINTF) + add_definitions(-DNEED_LIBPORT) +endif() + +# CPU bit order +set(fillorder FILLORDER_MSB2LSB) +if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i.*86.*" OR + CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64.*" OR + CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64.*") + set(fillorder FILLORDER_LSB2MSB) +endif() +set(HOST_FILLORDER ${fillorder} CACHE STRING "Native CPU bit order") +mark_as_advanced(HOST_FILLORDER) + +# CPU endianness +include(TestBigEndian) +test_big_endian(bigendian) +if(bigendian) + set(bigendian ON) +else() + set(bigendian OFF) +endif() +set(HOST_BIG_ENDIAN ${bigendian} CACHE STRING "Native CPU bit order") +mark_as_advanced(HOST_BIG_ENDIAN) +if(HOST_BIG_ENDIAN) + set(HOST_BIG_ENDIAN 1) +else() + set(HOST_BIG_ENDIAN 0) +endif() + +# IEEE floating point +set(HAVE_IEEEFP 1 CACHE STRING "IEEE floating point is available") +mark_as_advanced(HAVE_IEEEFP) + +# Large file support +if(UNIX OR MINGW) + # This might not catch every possibility catered for by + # AC_SYS_LARGEFILE. + add_definitions(-D_FILE_OFFSET_BITS=64) + set(FILE_OFFSET_BITS 64) +endif() + +# Documentation install directory (default to cmake project docdir) +set(LIBTIFF_DOCDIR "${CMAKE_INSTALL_FULL_DOCDIR}") + +# Options to enable and disable internal codecs + +option(ccitt "support for CCITT Group 3 & 4 algorithms" ON) +set(CCITT_SUPPORT ${ccitt}) + +option(packbits "support for Macintosh PackBits algorithm" ON) +set(PACKBITS_SUPPORT ${packbits}) + +option(lzw "support for LZW algorithm" ON) +set(LZW_SUPPORT ${lzw}) + +option(thunder "support for ThunderScan 4-bit RLE algorithm" ON) +set(THUNDER_SUPPORT ${thunder}) + +option(next "support for NeXT 2-bit RLE algorithm" ON) +set(NEXT_SUPPORT ${next}) + +option(logluv "support for LogLuv high dynamic range algorithm" ON) +set(LOGLUV_SUPPORT ${logluv}) + +# Option for Microsoft Document Imaging +option(mdi "support for Microsoft Document Imaging" ON) +set(MDI_SUPPORT ${mdi}) + +# ZLIB +set(ZLIB_SUPPORT 0) +if(ZLIB_LIBRARY) + set(ZLIB_SUPPORT 1) +endif() +set(ZIP_SUPPORT ${ZLIB_SUPPORT}) + +set(PIXARLOG_SUPPORT FALSE) + +# JPEG +set(JPEG_SUPPORT FALSE) +if(HAVE_JPEG) + set(JPEG_SUPPORT TRUE) + include_directories(${JPEG_INCLUDE_DIR}) +endif() + +option(old-jpeg "support for Old JPEG compression (read-only)" OFF) # OpenCV: changed to OFF +set(OJPEG_SUPPORT FALSE) +if(JPEG_SUPPORT AND old-jpeg) + set(OJPEG_SUPPORT TRUE) +endif() + +# OpenCV: turned off +set(JBIG_SUPPORT 0) +set(LZMA_SUPPORT 0) # OpenCV: turned off +set(JPEG12_FOUND FALSE) # OpenCV: turned off +set(STRIPCHOP_DEFAULT) +set(STRIP_SIZE_DEFAULT 8192) + +# Win32 IO +set(win32_io FALSE) if(WIN32 AND NOT WINRT) - set(USE_WIN32_FILEIO 1) + set(win32_io TRUE) +endif() +set(USE_WIN32_FILEIO ${win32_io} CACHE BOOL "Use win32 IO system (Microsoft Windows only)") +if(USE_WIN32_FILEIO) + set(USE_WIN32_FILEIO TRUE) +else() + set(USE_WIN32_FILEIO FALSE) endif() -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tif_config.h.cmakein" - "${CMAKE_CURRENT_BINARY_DIR}/tif_config.h" @ONLY) +# Orthogonal features + +# OpenCV: turned ON +set(SUBIFD_SUPPORT 1) +set(DEFAULT_EXTRASAMPLE_AS_ALPHA 1) +set(CHECK_JPEG_YCBCR_SUBSAMPLING 1) + +if(JPEG_INCLUDE_DIR) + list(APPEND TIFF_INCLUDES ${JPEG_INCLUDE_DIR}) +endif() +if(JPEG12_INCLUDE_DIR) + list(APPEND TIFF_INCLUDES ${JPEG12_INCLUDE_DIR}) +endif() +if(JBIG_INCLUDE_DIR) + list(APPEND TIFF_INCLUDES ${JBIG_INCLUDE_DIR}) +endif() +if(LIBLZMA_INCLUDE_DIRS) + list(APPEND TIFF_INCLUDES ${LIBLZMA_INCLUDE_DIRS}) +endif() + +# Libraries required by libtiff +set(TIFF_LIBRARY_DEPS) +if(M_LIBRARY) + list(APPEND TIFF_LIBRARY_DEPS ${M_LIBRARY}) +endif() +if(ZLIB_LIBRARIES) + list(APPEND TIFF_LIBRARY_DEPS ${ZLIB_LIBRARIES}) +endif() +if(JPEG_LIBRARIES) + list(APPEND TIFF_LIBRARY_DEPS ${JPEG_LIBRARIES}) +endif() +if(JPEG12_LIBRARIES) + list(APPEND TIFF_LIBRARY_DEPS ${JPEG12_LIBRARIES}) +endif() +if(JBIG_LIBRARIES) + list(APPEND TIFF_LIBRARY_DEPS ${JBIG_LIBRARIES}) +endif() +if(LIBLZMA_LIBRARIES) + list(APPEND TIFF_LIBRARY_DEPS ${LIBLZMA_LIBRARIES}) +endif() + + + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tif_config.h.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/tif_config.h" + @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tiffconf.h.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/tiffconf.h" + @ONLY) ocv_include_directories("${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" ${ZLIB_INCLUDE_DIRS}) @@ -79,6 +424,7 @@ set(lib_srcs uvcode.h tiffio.hxx "${CMAKE_CURRENT_BINARY_DIR}/tif_config.h" + "${CMAKE_CURRENT_BINARY_DIR}/tiffconf.h" ) if(WIN32 AND NOT WINRT) @@ -92,7 +438,9 @@ ocv_warnings_disable(CMAKE_C_FLAGS -Wno-unused-but-set-variable -Wmissing-protot -Wmisleading-indentation ) ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter) # clang -ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations -Wunused-parameter) +ocv_warnings_disable(CMAKE_CXX_FLAGS -Wmissing-declarations -Wunused-parameter + -Wundef # tiffiop.h: #if __clang_major__ >= 4 +) ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4018 /wd4100 /wd4127 /wd4311 /wd4701 /wd4706) # vs2005 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4244) # vs2008 ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4267 /wd4305 /wd4306) # vs2008 Win64 diff --git a/3rdparty/libtiff/tif_aux.c b/3rdparty/libtiff/tif_aux.c index bc1ba159c2..10b8d00c25 100644 --- a/3rdparty/libtiff/tif_aux.c +++ b/3rdparty/libtiff/tif_aux.c @@ -1,26 +1,26 @@ -/* $Id: tif_aux.c,v 1.26 2010-07-01 15:33:28 dron Exp $ */ +/* $Id: tif_aux.c,v 1.31 2017-11-17 20:21:00 erouault Exp $ */ /* * Copyright (c) 1991-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -36,126 +36,130 @@ uint32 _TIFFMultiply32(TIFF* tif, uint32 first, uint32 second, const char* where) { - uint32 bytes = first * second; + uint32 bytes = first * second; - if (second && bytes / second != first) { - TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where); - bytes = 0; - } + if (second && bytes / second != first) { + TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where); + bytes = 0; + } - return bytes; + return bytes; } uint64 _TIFFMultiply64(TIFF* tif, uint64 first, uint64 second, const char* where) { - uint64 bytes = first * second; + uint64 bytes = first * second; - if (second && bytes / second != first) { - TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where); - bytes = 0; - } + if (second && bytes / second != first) { + TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where); + bytes = 0; + } - return bytes; + return bytes; } void* _TIFFCheckRealloc(TIFF* tif, void* buffer, - tmsize_t nmemb, tmsize_t elem_size, const char* what) + tmsize_t nmemb, tmsize_t elem_size, const char* what) { - void* cp = NULL; - tmsize_t bytes = nmemb * elem_size; + void* cp = NULL; + tmsize_t bytes = nmemb * elem_size; - /* - * XXX: Check for integer overflow. - */ - if (nmemb && elem_size && bytes / elem_size == nmemb) - cp = _TIFFrealloc(buffer, bytes); + /* + * XXX: Check for integer overflow. + */ + if (nmemb && elem_size && bytes / elem_size == nmemb) + cp = _TIFFrealloc(buffer, bytes); - if (cp == NULL) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "Failed to allocate memory for %s " - "(%ld elements of %ld bytes each)", - what,(long) nmemb, (long) elem_size); - } + if (cp == NULL) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Failed to allocate memory for %s " + "(%ld elements of %ld bytes each)", + what,(long) nmemb, (long) elem_size); + } - return cp; + return cp; } void* _TIFFCheckMalloc(TIFF* tif, tmsize_t nmemb, tmsize_t elem_size, const char* what) { - return _TIFFCheckRealloc(tif, NULL, nmemb, elem_size, what); + return _TIFFCheckRealloc(tif, NULL, nmemb, elem_size, what); } static int TIFFDefaultTransferFunction(TIFFDirectory* td) { - uint16 **tf = td->td_transferfunction; - tmsize_t i, n, nbytes; + uint16 **tf = td->td_transferfunction; + tmsize_t i, n, nbytes; - tf[0] = tf[1] = tf[2] = 0; - if (td->td_bitspersample >= sizeof(tmsize_t) * 8 - 2) - return 0; + tf[0] = tf[1] = tf[2] = 0; + if (td->td_bitspersample >= sizeof(tmsize_t) * 8 - 2) + return 0; - n = ((tmsize_t)1)<td_bitspersample; - nbytes = n * sizeof (uint16); - if (!(tf[0] = (uint16 *)_TIFFmalloc(nbytes))) - return 0; - tf[0][0] = 0; - for (i = 1; i < n; i++) { - double t = (double)i/((double) n-1.); - tf[0][i] = (uint16)floor(65535.*pow(t, 2.2) + .5); - } + n = ((tmsize_t)1)<td_bitspersample; + nbytes = n * sizeof (uint16); + tf[0] = (uint16 *)_TIFFmalloc(nbytes); + if (tf[0] == NULL) + return 0; + tf[0][0] = 0; + for (i = 1; i < n; i++) { + double t = (double)i/((double) n-1.); + tf[0][i] = (uint16)floor(65535.*pow(t, 2.2) + .5); + } - if (td->td_samplesperpixel - td->td_extrasamples > 1) { - if (!(tf[1] = (uint16 *)_TIFFmalloc(nbytes))) - goto bad; - _TIFFmemcpy(tf[1], tf[0], nbytes); - if (!(tf[2] = (uint16 *)_TIFFmalloc(nbytes))) - goto bad; - _TIFFmemcpy(tf[2], tf[0], nbytes); - } - return 1; + if (td->td_samplesperpixel - td->td_extrasamples > 1) { + tf[1] = (uint16 *)_TIFFmalloc(nbytes); + if(tf[1] == NULL) + goto bad; + _TIFFmemcpy(tf[1], tf[0], nbytes); + tf[2] = (uint16 *)_TIFFmalloc(nbytes); + if (tf[2] == NULL) + goto bad; + _TIFFmemcpy(tf[2], tf[0], nbytes); + } + return 1; bad: - if (tf[0]) - _TIFFfree(tf[0]); - if (tf[1]) - _TIFFfree(tf[1]); - if (tf[2]) - _TIFFfree(tf[2]); - tf[0] = tf[1] = tf[2] = 0; - return 0; + if (tf[0]) + _TIFFfree(tf[0]); + if (tf[1]) + _TIFFfree(tf[1]); + if (tf[2]) + _TIFFfree(tf[2]); + tf[0] = tf[1] = tf[2] = 0; + return 0; } static int TIFFDefaultRefBlackWhite(TIFFDirectory* td) { - int i; + int i; - if (!(td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float)))) - return 0; + td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float)); + if (td->td_refblackwhite == NULL) + return 0; if (td->td_photometric == PHOTOMETRIC_YCBCR) { - /* - * YCbCr (Class Y) images must have the ReferenceBlackWhite - * tag set. Fix the broken images, which lacks that tag. - */ - td->td_refblackwhite[0] = 0.0F; - td->td_refblackwhite[1] = td->td_refblackwhite[3] = - td->td_refblackwhite[5] = 255.0F; - td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0F; - } else { - /* - * Assume RGB (Class R) - */ - for (i = 0; i < 3; i++) { - td->td_refblackwhite[2*i+0] = 0; - td->td_refblackwhite[2*i+1] = - (float)((1L<td_bitspersample)-1L); - } - } - return 1; + /* + * YCbCr (Class Y) images must have the ReferenceBlackWhite + * tag set. Fix the broken images, which lacks that tag. + */ + td->td_refblackwhite[0] = 0.0F; + td->td_refblackwhite[1] = td->td_refblackwhite[3] = + td->td_refblackwhite[5] = 255.0F; + td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0F; + } else { + /* + * Assume RGB (Class R) + */ + for (i = 0; i < 3; i++) { + td->td_refblackwhite[2*i+0] = 0; + td->td_refblackwhite[2*i+1] = + (float)((1L<td_bitspersample)-1L); + } + } + return 1; } /* @@ -163,132 +167,139 @@ TIFFDefaultRefBlackWhite(TIFFDirectory* td) * value if the tag is not present in the directory. * * NB: We use the value in the directory, rather than - * explcit values so that defaults exist only one + * explicit values so that defaults exist only one * place in the library -- in TIFFDefaultDirectory. */ int TIFFVGetFieldDefaulted(TIFF* tif, uint32 tag, va_list ap) { - TIFFDirectory *td = &tif->tif_dir; + TIFFDirectory *td = &tif->tif_dir; - if (TIFFVGetField(tif, tag, ap)) - return (1); - switch (tag) { - case TIFFTAG_SUBFILETYPE: - *va_arg(ap, uint32 *) = td->td_subfiletype; - return (1); - case TIFFTAG_BITSPERSAMPLE: - *va_arg(ap, uint16 *) = td->td_bitspersample; - return (1); - case TIFFTAG_THRESHHOLDING: - *va_arg(ap, uint16 *) = td->td_threshholding; - return (1); - case TIFFTAG_FILLORDER: - *va_arg(ap, uint16 *) = td->td_fillorder; - return (1); - case TIFFTAG_ORIENTATION: - *va_arg(ap, uint16 *) = td->td_orientation; - return (1); - case TIFFTAG_SAMPLESPERPIXEL: - *va_arg(ap, uint16 *) = td->td_samplesperpixel; - return (1); - case TIFFTAG_ROWSPERSTRIP: - *va_arg(ap, uint32 *) = td->td_rowsperstrip; - return (1); - case TIFFTAG_MINSAMPLEVALUE: - *va_arg(ap, uint16 *) = td->td_minsamplevalue; - return (1); - case TIFFTAG_MAXSAMPLEVALUE: - *va_arg(ap, uint16 *) = td->td_maxsamplevalue; - return (1); - case TIFFTAG_PLANARCONFIG: - *va_arg(ap, uint16 *) = td->td_planarconfig; - return (1); - case TIFFTAG_RESOLUTIONUNIT: - *va_arg(ap, uint16 *) = td->td_resolutionunit; - return (1); - case TIFFTAG_PREDICTOR: - { - TIFFPredictorState* sp = (TIFFPredictorState*) tif->tif_data; - *va_arg(ap, uint16*) = (uint16) sp->predictor; - return 1; - } - case TIFFTAG_DOTRANGE: - *va_arg(ap, uint16 *) = 0; - *va_arg(ap, uint16 *) = (1<td_bitspersample)-1; - return (1); - case TIFFTAG_INKSET: - *va_arg(ap, uint16 *) = INKSET_CMYK; + if (TIFFVGetField(tif, tag, ap)) + return (1); + switch (tag) { + case TIFFTAG_SUBFILETYPE: + *va_arg(ap, uint32 *) = td->td_subfiletype; + return (1); + case TIFFTAG_BITSPERSAMPLE: + *va_arg(ap, uint16 *) = td->td_bitspersample; + return (1); + case TIFFTAG_THRESHHOLDING: + *va_arg(ap, uint16 *) = td->td_threshholding; + return (1); + case TIFFTAG_FILLORDER: + *va_arg(ap, uint16 *) = td->td_fillorder; + return (1); + case TIFFTAG_ORIENTATION: + *va_arg(ap, uint16 *) = td->td_orientation; + return (1); + case TIFFTAG_SAMPLESPERPIXEL: + *va_arg(ap, uint16 *) = td->td_samplesperpixel; + return (1); + case TIFFTAG_ROWSPERSTRIP: + *va_arg(ap, uint32 *) = td->td_rowsperstrip; + return (1); + case TIFFTAG_MINSAMPLEVALUE: + *va_arg(ap, uint16 *) = td->td_minsamplevalue; + return (1); + case TIFFTAG_MAXSAMPLEVALUE: + *va_arg(ap, uint16 *) = td->td_maxsamplevalue; + return (1); + case TIFFTAG_PLANARCONFIG: + *va_arg(ap, uint16 *) = td->td_planarconfig; + return (1); + case TIFFTAG_RESOLUTIONUNIT: + *va_arg(ap, uint16 *) = td->td_resolutionunit; + return (1); + case TIFFTAG_PREDICTOR: + { + TIFFPredictorState* sp = (TIFFPredictorState*) tif->tif_data; + if( sp == NULL ) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Cannot get \"Predictor\" tag as plugin is not configured"); + *va_arg(ap, uint16*) = 0; + return 0; + } + *va_arg(ap, uint16*) = (uint16) sp->predictor; return 1; - case TIFFTAG_NUMBEROFINKS: - *va_arg(ap, uint16 *) = 4; - return (1); - case TIFFTAG_EXTRASAMPLES: - *va_arg(ap, uint16 *) = td->td_extrasamples; - *va_arg(ap, uint16 **) = td->td_sampleinfo; - return (1); - case TIFFTAG_MATTEING: - *va_arg(ap, uint16 *) = - (td->td_extrasamples == 1 && - td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA); - return (1); - case TIFFTAG_TILEDEPTH: - *va_arg(ap, uint32 *) = td->td_tiledepth; - return (1); - case TIFFTAG_DATATYPE: - *va_arg(ap, uint16 *) = td->td_sampleformat-1; - return (1); - case TIFFTAG_SAMPLEFORMAT: - *va_arg(ap, uint16 *) = td->td_sampleformat; - return(1); - case TIFFTAG_IMAGEDEPTH: - *va_arg(ap, uint32 *) = td->td_imagedepth; - return (1); - case TIFFTAG_YCBCRCOEFFICIENTS: - { - /* defaults are from CCIR Recommendation 601-1 */ - static float ycbcrcoeffs[] = { 0.299f, 0.587f, 0.114f }; - *va_arg(ap, float **) = ycbcrcoeffs; - return 1; - } - case TIFFTAG_YCBCRSUBSAMPLING: - *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[0]; - *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[1]; - return (1); - case TIFFTAG_YCBCRPOSITIONING: - *va_arg(ap, uint16 *) = td->td_ycbcrpositioning; - return (1); - case TIFFTAG_WHITEPOINT: - { - static float whitepoint[2]; - - /* TIFF 6.0 specification tells that it is no default - value for the WhitePoint, but AdobePhotoshop TIFF - Technical Note tells that it should be CIE D50. */ - whitepoint[0] = D50_X0 / (D50_X0 + D50_Y0 + D50_Z0); - whitepoint[1] = D50_Y0 / (D50_X0 + D50_Y0 + D50_Z0); - *va_arg(ap, float **) = whitepoint; - return 1; - } - case TIFFTAG_TRANSFERFUNCTION: - if (!td->td_transferfunction[0] && - !TIFFDefaultTransferFunction(td)) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "No space for \"TransferFunction\" tag"); - return (0); - } - *va_arg(ap, uint16 **) = td->td_transferfunction[0]; - if (td->td_samplesperpixel - td->td_extrasamples > 1) { - *va_arg(ap, uint16 **) = td->td_transferfunction[1]; - *va_arg(ap, uint16 **) = td->td_transferfunction[2]; - } - return (1); - case TIFFTAG_REFERENCEBLACKWHITE: - if (!td->td_refblackwhite && !TIFFDefaultRefBlackWhite(td)) - return (0); - *va_arg(ap, float **) = td->td_refblackwhite; - return (1); } - return 0; + case TIFFTAG_DOTRANGE: + *va_arg(ap, uint16 *) = 0; + *va_arg(ap, uint16 *) = (1<td_bitspersample)-1; + return (1); + case TIFFTAG_INKSET: + *va_arg(ap, uint16 *) = INKSET_CMYK; + return 1; + case TIFFTAG_NUMBEROFINKS: + *va_arg(ap, uint16 *) = 4; + return (1); + case TIFFTAG_EXTRASAMPLES: + *va_arg(ap, uint16 *) = td->td_extrasamples; + *va_arg(ap, uint16 **) = td->td_sampleinfo; + return (1); + case TIFFTAG_MATTEING: + *va_arg(ap, uint16 *) = + (td->td_extrasamples == 1 && + td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA); + return (1); + case TIFFTAG_TILEDEPTH: + *va_arg(ap, uint32 *) = td->td_tiledepth; + return (1); + case TIFFTAG_DATATYPE: + *va_arg(ap, uint16 *) = td->td_sampleformat-1; + return (1); + case TIFFTAG_SAMPLEFORMAT: + *va_arg(ap, uint16 *) = td->td_sampleformat; + return(1); + case TIFFTAG_IMAGEDEPTH: + *va_arg(ap, uint32 *) = td->td_imagedepth; + return (1); + case TIFFTAG_YCBCRCOEFFICIENTS: + { + /* defaults are from CCIR Recommendation 601-1 */ + static float ycbcrcoeffs[] = { 0.299f, 0.587f, 0.114f }; + *va_arg(ap, float **) = ycbcrcoeffs; + return 1; + } + case TIFFTAG_YCBCRSUBSAMPLING: + *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[0]; + *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[1]; + return (1); + case TIFFTAG_YCBCRPOSITIONING: + *va_arg(ap, uint16 *) = td->td_ycbcrpositioning; + return (1); + case TIFFTAG_WHITEPOINT: + { + static float whitepoint[2]; + + /* TIFF 6.0 specification tells that it is no default + value for the WhitePoint, but AdobePhotoshop TIFF + Technical Note tells that it should be CIE D50. */ + whitepoint[0] = D50_X0 / (D50_X0 + D50_Y0 + D50_Z0); + whitepoint[1] = D50_Y0 / (D50_X0 + D50_Y0 + D50_Z0); + *va_arg(ap, float **) = whitepoint; + return 1; + } + case TIFFTAG_TRANSFERFUNCTION: + if (!td->td_transferfunction[0] && + !TIFFDefaultTransferFunction(td)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "No space for \"TransferFunction\" tag"); + return (0); + } + *va_arg(ap, uint16 **) = td->td_transferfunction[0]; + if (td->td_samplesperpixel - td->td_extrasamples > 1) { + *va_arg(ap, uint16 **) = td->td_transferfunction[1]; + *va_arg(ap, uint16 **) = td->td_transferfunction[2]; + } + return (1); + case TIFFTAG_REFERENCEBLACKWHITE: + if (!td->td_refblackwhite && !TIFFDefaultRefBlackWhite(td)) + return (0); + *va_arg(ap, float **) = td->td_refblackwhite; + return (1); + } + return 0; } /* @@ -298,54 +309,61 @@ TIFFVGetFieldDefaulted(TIFF* tif, uint32 tag, va_list ap) int TIFFGetFieldDefaulted(TIFF* tif, uint32 tag, ...) { - int ok; - va_list ap; + int ok; + va_list ap; - va_start(ap, tag); - ok = TIFFVGetFieldDefaulted(tif, tag, ap); - va_end(ap); - return (ok); + va_start(ap, tag); + ok = TIFFVGetFieldDefaulted(tif, tag, ap); + va_end(ap); + return (ok); } struct _Int64Parts { - int32 low, high; + int32 low, high; }; typedef union { - struct _Int64Parts part; - int64 value; + struct _Int64Parts part; + int64 value; } _Int64; float _TIFFUInt64ToFloat(uint64 ui64) { - _Int64 i; + _Int64 i; - i.value = ui64; - if (i.part.high >= 0) { - return (float)i.value; - } else { - long double df; - df = (long double)i.value; - df += 18446744073709551616.0; /* adding 2**64 */ - return (float)df; - } + i.value = ui64; + if (i.part.high >= 0) { + return (float)i.value; + } else { + long double df; + df = (long double)i.value; + df += 18446744073709551616.0; /* adding 2**64 */ + return (float)df; + } } double _TIFFUInt64ToDouble(uint64 ui64) { - _Int64 i; + _Int64 i; - i.value = ui64; - if (i.part.high >= 0) { - return (double)i.value; - } else { - long double df; - df = (long double)i.value; - df += 18446744073709551616.0; /* adding 2**64 */ - return (double)df; - } + i.value = ui64; + if (i.part.high >= 0) { + return (double)i.value; + } else { + long double df; + df = (long double)i.value; + df += 18446744073709551616.0; /* adding 2**64 */ + return (double)df; + } +} + +int _TIFFSeekOK(TIFF* tif, toff_t off) +{ + /* Huge offsets, especially -1 / UINT64_MAX, can cause issues */ + /* See http://bugzilla.maptools.org/show_bug.cgi?id=2726 */ + return off <= (~(uint64)0)/2 && TIFFSeekFile(tif,off,SEEK_SET)==off; } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_close.c b/3rdparty/libtiff/tif_close.c index 43793d8642..a0cb661311 100644 --- a/3rdparty/libtiff/tif_close.c +++ b/3rdparty/libtiff/tif_close.c @@ -1,26 +1,26 @@ -/* $Id: tif_close.c,v 1.19 2010-03-10 18:56:48 bfriesen Exp $ */ +/* $Id: tif_close.c,v 1.21 2016-01-23 21:20:34 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -36,61 +36,61 @@ /** * Auxiliary function to free the TIFF structure. Given structure will be - * completetly freed, so you should save opened file handle and pointer + * completely freed, so you should save opened file handle and pointer * to the close procedure in external variables before calling * _TIFFCleanup(), if you will need these ones to close the file. - * + * * @param tif A TIFF pointer. */ void TIFFCleanup(TIFF* tif) { - /* + /* * Flush buffered data and directory (if dirty). */ - if (tif->tif_mode != O_RDONLY) - TIFFFlush(tif); - (*tif->tif_cleanup)(tif); - TIFFFreeDirectory(tif); + if (tif->tif_mode != O_RDONLY) + TIFFFlush(tif); + (*tif->tif_cleanup)(tif); + TIFFFreeDirectory(tif); - if (tif->tif_dirlist) - _TIFFfree(tif->tif_dirlist); + if (tif->tif_dirlist) + _TIFFfree(tif->tif_dirlist); - /* + /* * Clean up client info links. */ - while( tif->tif_clientinfo ) - { - TIFFClientInfoLink *link = tif->tif_clientinfo; + while( tif->tif_clientinfo ) + { + TIFFClientInfoLink *psLink = tif->tif_clientinfo; - tif->tif_clientinfo = link->next; - _TIFFfree( link->name ); - _TIFFfree( link ); - } + tif->tif_clientinfo = psLink->next; + _TIFFfree( psLink->name ); + _TIFFfree( psLink ); + } - if (tif->tif_rawdata && (tif->tif_flags&TIFF_MYBUFFER)) - _TIFFfree(tif->tif_rawdata); - if (isMapped(tif)) - TIFFUnmapFileContents(tif, tif->tif_base, (toff_t)tif->tif_size); + if (tif->tif_rawdata && (tif->tif_flags&TIFF_MYBUFFER)) + _TIFFfree(tif->tif_rawdata); + if (isMapped(tif)) + TIFFUnmapFileContents(tif, tif->tif_base, (toff_t)tif->tif_size); - /* + /* * Clean up custom fields. */ - if (tif->tif_fields && tif->tif_nfields > 0) { - uint32 i; + if (tif->tif_fields && tif->tif_nfields > 0) { + uint32 i; - for (i = 0; i < tif->tif_nfields; i++) { - TIFFField *fld = tif->tif_fields[i]; - if (fld->field_bit == FIELD_CUSTOM && - strncmp("Tag ", fld->field_name, 4) == 0) { - _TIFFfree(fld->field_name); - _TIFFfree(fld); - } - } + for (i = 0; i < tif->tif_nfields; i++) { + TIFFField *fld = tif->tif_fields[i]; + if (fld->field_bit == FIELD_CUSTOM && + strncmp("Tag ", fld->field_name, 4) == 0) { + _TIFFfree(fld->field_name); + _TIFFfree(fld); + } + } - _TIFFfree(tif->tif_fields); - } + _TIFFfree(tif->tif_fields); + } if (tif->tif_nfieldscompat > 0) { uint32 i; @@ -102,7 +102,7 @@ TIFFCleanup(TIFF* tif) _TIFFfree(tif->tif_fieldscompat); } - _TIFFfree(tif); + _TIFFfree(tif); } /************************************************************************/ @@ -115,18 +115,18 @@ TIFFCleanup(TIFF* tif) * TIFFClose closes a file that was previously opened with TIFFOpen(). * Any buffered data are flushed to the file, including the contents of * the current directory (if modified); and all resources are reclaimed. - * + * * @param tif A TIFF pointer. */ void TIFFClose(TIFF* tif) { - TIFFCloseProc closeproc = tif->tif_closeproc; - thandle_t fd = tif->tif_clientdata; + TIFFCloseProc closeproc = tif->tif_closeproc; + thandle_t fd = tif->tif_clientdata; - TIFFCleanup(tif); - (void) (*closeproc)(fd); + TIFFCleanup(tif); + (void) (*closeproc)(fd); } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_codec.c b/3rdparty/libtiff/tif_codec.c index 48db47ca62..7cb46f6304 100644 --- a/3rdparty/libtiff/tif_codec.c +++ b/3rdparty/libtiff/tif_codec.c @@ -1,26 +1,26 @@ -/* $Id: tif_codec.c,v 1.15 2010-12-14 12:53:00 dron Exp $ */ +/* $Id: tif_codec.c,v 1.17 2015-08-19 02:31:04 bfriesen Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -94,7 +94,7 @@ TIFFCodec _TIFFBuiltinCODECS[] = { { "CCITT Group 4", COMPRESSION_CCITTFAX4, TIFFInitCCITTFax4 }, { "ISO JBIG", COMPRESSION_JBIG, TIFFInitJBIG }, { "Deflate", COMPRESSION_DEFLATE, TIFFInitZIP }, - { "AdobeDeflate", COMPRESSION_ADOBE_DEFLATE , TIFFInitZIP }, + { "AdobeDeflate", COMPRESSION_ADOBE_DEFLATE , TIFFInitZIP }, { "PixarLog", COMPRESSION_PIXARLOG, TIFFInitPixarLog }, { "SGILog", COMPRESSION_SGILOG, TIFFInitSGILog }, { "SGILog24", COMPRESSION_SGILOG24, TIFFInitSGILog }, @@ -105,27 +105,27 @@ TIFFCodec _TIFFBuiltinCODECS[] = { static int _notConfigured(TIFF* tif) { - const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); + const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); char compression_code[20]; - - sprintf( compression_code, "%d", tif->tif_dir.td_compression ); - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "%s compression support is not configured", + + sprintf(compression_code, "%d",tif->tif_dir.td_compression ); + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%s compression support is not configured", c ? c->name : compression_code ); - return (0); + return (0); } static int NotConfigured(TIFF* tif, int scheme) { - (void) scheme; + (void) scheme; - tif->tif_fixuptags = _notConfigured; - tif->tif_decodestatus = FALSE; - tif->tif_setupdecode = _notConfigured; - tif->tif_encodestatus = FALSE; - tif->tif_setupencode = _notConfigured; - return (1); + tif->tif_fixuptags = _notConfigured; + tif->tif_decodestatus = FALSE; + tif->tif_setupdecode = _notConfigured; + tif->tif_encodestatus = FALSE; + tif->tif_setupencode = _notConfigured; + return (1); } /************************************************************************/ @@ -142,18 +142,18 @@ NotConfigured(TIFF* tif, int scheme) int TIFFIsCODECConfigured(uint16 scheme) { - const TIFFCodec* codec = TIFFFindCODEC(scheme); + const TIFFCodec* codec = TIFFFindCODEC(scheme); - if(codec == NULL) { - return 0; - } - if(codec->init == NULL) { - return 0; - } - if(codec->init != NotConfigured){ - return 1; - } - return 0; + if(codec == NULL) { + return 0; + } + if(codec->init == NULL) { + return 0; + } + if(codec->init != NotConfigured){ + return 1; + } + return 0; } /* diff --git a/3rdparty/libtiff/tif_color.c b/3rdparty/libtiff/tif_color.c index f965b519ba..71cafcde6c 100644 --- a/3rdparty/libtiff/tif_color.c +++ b/3rdparty/libtiff/tif_color.c @@ -1,26 +1,26 @@ -/* $Id: tif_color.c,v 1.19 2010-12-14 02:22:42 faxguy Exp $ */ +/* $Id: tif_color.c,v 1.24 2017-05-29 10:12:54 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -44,30 +44,30 @@ */ void TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b, - float *X, float *Y, float *Z) + float *X, float *Y, float *Z) { - float L = (float)l * 100.0F / 255.0F; - float cby, tmp; + float L = (float)l * 100.0F / 255.0F; + float cby, tmp; - if( L < 8.856F ) { - *Y = (L * cielab->Y0) / 903.292F; - cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F; - } else { - cby = (L + 16.0F) / 116.0F; - *Y = cielab->Y0 * cby * cby * cby; - } + if( L < 8.856F ) { + *Y = (L * cielab->Y0) / 903.292F; + cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F; + } else { + cby = (L + 16.0F) / 116.0F; + *Y = cielab->Y0 * cby * cby * cby; + } - tmp = (float)a / 500.0F + cby; - if( tmp < 0.2069F ) - *X = cielab->X0 * (tmp - 0.13793F) / 7.787F; - else - *X = cielab->X0 * tmp * tmp * tmp; + tmp = (float)a / 500.0F + cby; + if( tmp < 0.2069F ) + *X = cielab->X0 * (tmp - 0.13793F) / 7.787F; + else + *X = cielab->X0 * tmp * tmp * tmp; - tmp = cby - (float)b / 200.0F; - if( tmp < 0.2069F ) - *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F; - else - *Z = cielab->Z0 * tmp * tmp * tmp; + tmp = cby - (float)b / 200.0F; + if( tmp < 0.2069F ) + *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F; + else + *Z = cielab->Z0 * tmp * tmp * tmp; } #define RINT(R) ((uint32)((R)>0?((R)+0.5):((R)-0.5))) @@ -76,98 +76,98 @@ TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b, */ void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z, - uint32 *r, uint32 *g, uint32 *b) + uint32 *r, uint32 *g, uint32 *b) { - int i; - float Yr, Yg, Yb; - float *matrix = &cielab->display.d_mat[0][0]; + int i; + float Yr, Yg, Yb; + float *matrix = &cielab->display.d_mat[0][0]; - /* Multiply through the matrix to get luminosity values. */ - Yr = matrix[0] * X + matrix[1] * Y + matrix[2] * Z; - Yg = matrix[3] * X + matrix[4] * Y + matrix[5] * Z; - Yb = matrix[6] * X + matrix[7] * Y + matrix[8] * Z; + /* Multiply through the matrix to get luminosity values. */ + Yr = matrix[0] * X + matrix[1] * Y + matrix[2] * Z; + Yg = matrix[3] * X + matrix[4] * Y + matrix[5] * Z; + Yb = matrix[6] * X + matrix[7] * Y + matrix[8] * Z; - /* Clip input */ - Yr = TIFFmax(Yr, cielab->display.d_Y0R); - Yg = TIFFmax(Yg, cielab->display.d_Y0G); - Yb = TIFFmax(Yb, cielab->display.d_Y0B); + /* Clip input */ + Yr = TIFFmax(Yr, cielab->display.d_Y0R); + Yg = TIFFmax(Yg, cielab->display.d_Y0G); + Yb = TIFFmax(Yb, cielab->display.d_Y0B); - /* Avoid overflow in case of wrong input values */ - Yr = TIFFmin(Yr, cielab->display.d_YCR); - Yg = TIFFmin(Yg, cielab->display.d_YCG); - Yb = TIFFmin(Yb, cielab->display.d_YCB); + /* Avoid overflow in case of wrong input values */ + Yr = TIFFmin(Yr, cielab->display.d_YCR); + Yg = TIFFmin(Yg, cielab->display.d_YCG); + Yb = TIFFmin(Yb, cielab->display.d_YCB); - /* Turn luminosity to colour value. */ - i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep); - i = TIFFmin(cielab->range, i); - *r = RINT(cielab->Yr2r[i]); + /* Turn luminosity to colour value. */ + i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep); + i = TIFFmin(cielab->range, i); + *r = RINT(cielab->Yr2r[i]); - i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep); - i = TIFFmin(cielab->range, i); - *g = RINT(cielab->Yg2g[i]); + i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep); + i = TIFFmin(cielab->range, i); + *g = RINT(cielab->Yg2g[i]); - i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep); - i = TIFFmin(cielab->range, i); - *b = RINT(cielab->Yb2b[i]); + i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep); + i = TIFFmin(cielab->range, i); + *b = RINT(cielab->Yb2b[i]); - /* Clip output. */ - *r = TIFFmin(*r, cielab->display.d_Vrwr); - *g = TIFFmin(*g, cielab->display.d_Vrwg); - *b = TIFFmin(*b, cielab->display.d_Vrwb); + /* Clip output. */ + *r = TIFFmin(*r, cielab->display.d_Vrwr); + *g = TIFFmin(*g, cielab->display.d_Vrwg); + *b = TIFFmin(*b, cielab->display.d_Vrwb); } #undef RINT -/* +/* * Allocate conversion state structures and make look_up tables for * the Yr,Yb,Yg <=> r,g,b conversions. */ int TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab, - const TIFFDisplay *display, float *refWhite) + const TIFFDisplay *display, float *refWhite) { - int i; - double gamma; + int i; + double dfGamma; - cielab->range = CIELABTORGB_TABLE_RANGE; + cielab->range = CIELABTORGB_TABLE_RANGE; - _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay)); + _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay)); - /* Red */ - gamma = 1.0 / cielab->display.d_gammaR ; - cielab->rstep = - (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; - for(i = 0; i <= cielab->range; i++) { - cielab->Yr2r[i] = cielab->display.d_Vrwr - * ((float)pow((double)i / cielab->range, gamma)); - } + /* Red */ + dfGamma = 1.0 / cielab->display.d_gammaR ; + cielab->rstep = + (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; + for(i = 0; i <= cielab->range; i++) { + cielab->Yr2r[i] = cielab->display.d_Vrwr + * ((float)pow((double)i / cielab->range, dfGamma)); + } - /* Green */ - gamma = 1.0 / cielab->display.d_gammaG ; - cielab->gstep = - (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; - for(i = 0; i <= cielab->range; i++) { - cielab->Yg2g[i] = cielab->display.d_Vrwg - * ((float)pow((double)i / cielab->range, gamma)); - } + /* Green */ + dfGamma = 1.0 / cielab->display.d_gammaG ; + cielab->gstep = + (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; + for(i = 0; i <= cielab->range; i++) { + cielab->Yg2g[i] = cielab->display.d_Vrwg + * ((float)pow((double)i / cielab->range, dfGamma)); + } - /* Blue */ - gamma = 1.0 / cielab->display.d_gammaB ; - cielab->bstep = - (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; - for(i = 0; i <= cielab->range; i++) { - cielab->Yb2b[i] = cielab->display.d_Vrwb - * ((float)pow((double)i / cielab->range, gamma)); - } + /* Blue */ + dfGamma = 1.0 / cielab->display.d_gammaB ; + cielab->bstep = + (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; + for(i = 0; i <= cielab->range; i++) { + cielab->Yb2b[i] = cielab->display.d_Vrwb + * ((float)pow((double)i / cielab->range, dfGamma)); + } - /* Init reference white point */ - cielab->X0 = refWhite[0]; - cielab->Y0 = refWhite[1]; - cielab->Z0 = refWhite[2]; + /* Init reference white point */ + cielab->X0 = refWhite[0]; + cielab->Y0 = refWhite[1]; + cielab->Z0 = refWhite[2]; - return 0; + return 0; } -/* +/* * Convert color value from the YCbCr space to CIE XYZ. * The colorspace conversion algorithm comes from the IJG v5a code; * see below for more information on how it works. @@ -175,26 +175,45 @@ TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab, #define SHIFT 16 #define FIX(x) ((int32)((x) * (1L<(max)?(max):(f)) #define HICLAMP(f,max) ((f)>(max)?(max):(f)) void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr, - uint32 *r, uint32 *g, uint32 *b) + uint32 *r, uint32 *g, uint32 *b) { - int32 i; + int32 i; - /* XXX: Only 8-bit YCbCr input supported for now */ - Y = HICLAMP(Y, 255), Cb = CLAMP(Cb, 0, 255), Cr = CLAMP(Cr, 0, 255); + /* XXX: Only 8-bit YCbCr input supported for now */ + Y = HICLAMP(Y, 255); + Cb = CLAMP(Cb, 0, 255); + Cr = CLAMP(Cr, 0, 255); - i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]; - *r = CLAMP(i, 0, 255); - i = ycbcr->Y_tab[Y] - + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT); - *g = CLAMP(i, 0, 255); - i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]; - *b = CLAMP(i, 0, 255); + i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]; + *r = CLAMP(i, 0, 255); + i = ycbcr->Y_tab[Y] + + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT); + *g = CLAMP(i, 0, 255); + i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]; + *b = CLAMP(i, 0, 255); +} + +/* Clamp function for sanitization purposes. Normally clamping should not */ +/* occur for well behaved chroma and refBlackWhite coefficients */ +static float CLAMPw(float v, float vmin, float vmax) +{ + if( v < vmin ) + { + /* printf("%f clamped to %f\n", v, vmin); */ + return vmin; + } + if( v > vmax ) + { + /* printf("%f clamped to %f\n", v, vmax); */ + return vmax; + } + return v; } /* @@ -218,17 +237,17 @@ TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite) { TIFFRGBValue* clamptab; int i; - + #define LumaRed luma[0] #define LumaGreen luma[1] #define LumaBlue luma[2] clamptab = (TIFFRGBValue*)( - (uint8*) ycbcr+TIFFroundup_32(sizeof (TIFFYCbCrToRGB), sizeof (long))); + (uint8*) ycbcr+TIFFroundup_32(sizeof (TIFFYCbCrToRGB), sizeof (long))); _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */ ycbcr->clamptab = (clamptab += 256); for (i = 0; i < 256; i++) - clamptab[i] = (TIFFRGBValue) i; + clamptab[i] = (TIFFRGBValue) i; _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */ ycbcr->Cr_r_tab = (int*) (clamptab + 3*256); ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256; @@ -236,16 +255,16 @@ TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite) ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256; ycbcr->Y_tab = ycbcr->Cb_g_tab + 256; - { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1); - float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2); - float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3); - float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4); + { float f1 = 2-2*LumaRed; int32 D1 = FIX(CLAMP(f1,0.0F,2.0F)); + float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(CLAMP(f2,0.0F,2.0F)); + float f3 = 2-2*LumaBlue; int32 D3 = FIX(CLAMP(f3,0.0F,2.0F)); + float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(CLAMP(f4,0.0F,2.0F)); int x; #undef LumaBlue #undef LumaGreen #undef LumaRed - + /* * i is the actual input pixel value in the range 0..255 * Cb and Cr values are in the range -128..127 (actually @@ -254,17 +273,20 @@ TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite) * constructing tables indexed by the raw pixel data. */ for (i = 0, x = -128; i < 256; i++, x++) { - int32 Cr = (int32)Code2V(x, refBlackWhite[4] - 128.0F, - refBlackWhite[5] - 128.0F, 127); - int32 Cb = (int32)Code2V(x, refBlackWhite[2] - 128.0F, - refBlackWhite[3] - 128.0F, 127); + int32 Cr = (int32)CLAMPw(Code2V(x, refBlackWhite[4] - 128.0F, + refBlackWhite[5] - 128.0F, 127), + -128.0F * 32, 128.0F * 32); + int32 Cb = (int32)CLAMPw(Code2V(x, refBlackWhite[2] - 128.0F, + refBlackWhite[3] - 128.0F, 127), + -128.0F * 32, 128.0F * 32); - ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT); - ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT); - ycbcr->Cr_g_tab[i] = D2*Cr; - ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF; - ycbcr->Y_tab[i] = - (int32)Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255); + ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT); + ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT); + ycbcr->Cr_g_tab[i] = D2*Cr; + ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF; + ycbcr->Y_tab[i] = + (int32)CLAMPw(Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255), + -128.0F * 32, 128.0F * 32); } } diff --git a/3rdparty/libtiff/tif_compress.c b/3rdparty/libtiff/tif_compress.c index 6c27eaa878..b571d19545 100644 --- a/3rdparty/libtiff/tif_compress.c +++ b/3rdparty/libtiff/tif_compress.c @@ -1,26 +1,26 @@ -/* $Id: tif_compress.c,v 1.22 2010-03-10 18:56:48 bfriesen Exp $ */ +/* $Id: tif_compress.c,v 1.25 2016-10-25 20:04:22 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -34,99 +34,99 @@ static int TIFFNoEncode(TIFF* tif, const char* method) { - const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); + const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); - if (c) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "%s %s encoding is not implemented", - c->name, method); - } else { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "Compression scheme %u %s encoding is not implemented", - tif->tif_dir.td_compression, method); - } - return (-1); + if (c) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%s %s encoding is not implemented", + c->name, method); + } else { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Compression scheme %u %s encoding is not implemented", + tif->tif_dir.td_compression, method); + } + return (-1); } int _TIFFNoRowEncode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s) { - (void) pp; (void) cc; (void) s; - return (TIFFNoEncode(tif, "scanline")); + (void) pp; (void) cc; (void) s; + return (TIFFNoEncode(tif, "scanline")); } int _TIFFNoStripEncode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s) { - (void) pp; (void) cc; (void) s; - return (TIFFNoEncode(tif, "strip")); + (void) pp; (void) cc; (void) s; + return (TIFFNoEncode(tif, "strip")); } int _TIFFNoTileEncode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s) { - (void) pp; (void) cc; (void) s; - return (TIFFNoEncode(tif, "tile")); + (void) pp; (void) cc; (void) s; + return (TIFFNoEncode(tif, "tile")); } static int TIFFNoDecode(TIFF* tif, const char* method) { - const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); + const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression); - if (c) - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "%s %s decoding is not implemented", - c->name, method); - else - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "Compression scheme %u %s decoding is not implemented", - tif->tif_dir.td_compression, method); - return (-1); + if (c) + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%s %s decoding is not implemented", + c->name, method); + else + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Compression scheme %u %s decoding is not implemented", + tif->tif_dir.td_compression, method); + return (0); } -int +static int _TIFFNoFixupTags(TIFF* tif) { - (void) tif; - return (1); + (void) tif; + return (1); } int _TIFFNoRowDecode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s) { - (void) pp; (void) cc; (void) s; - return (TIFFNoDecode(tif, "scanline")); + (void) pp; (void) cc; (void) s; + return (TIFFNoDecode(tif, "scanline")); } int _TIFFNoStripDecode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s) { - (void) pp; (void) cc; (void) s; - return (TIFFNoDecode(tif, "strip")); + (void) pp; (void) cc; (void) s; + return (TIFFNoDecode(tif, "strip")); } int _TIFFNoTileDecode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s) { - (void) pp; (void) cc; (void) s; - return (TIFFNoDecode(tif, "tile")); + (void) pp; (void) cc; (void) s; + return (TIFFNoDecode(tif, "tile")); } int _TIFFNoSeek(TIFF* tif, uint32 off) { - (void) off; - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "Compression algorithm does not support random access"); - return (0); + (void) off; + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Compression algorithm does not support random access"); + return (0); } int _TIFFNoPreCode(TIFF* tif, uint16 s) { - (void) tif; (void) s; - return (1); + (void) tif; (void) s; + return (1); } static int _TIFFtrue(TIFF* tif) { (void) tif; return (1); } @@ -135,41 +135,41 @@ static void _TIFFvoid(TIFF* tif) { (void) tif; } void _TIFFSetDefaultCompressionState(TIFF* tif) { - tif->tif_fixuptags = _TIFFNoFixupTags; - tif->tif_decodestatus = TRUE; - tif->tif_setupdecode = _TIFFtrue; - tif->tif_predecode = _TIFFNoPreCode; - tif->tif_decoderow = _TIFFNoRowDecode; - tif->tif_decodestrip = _TIFFNoStripDecode; - tif->tif_decodetile = _TIFFNoTileDecode; - tif->tif_encodestatus = TRUE; - tif->tif_setupencode = _TIFFtrue; - tif->tif_preencode = _TIFFNoPreCode; - tif->tif_postencode = _TIFFtrue; - tif->tif_encoderow = _TIFFNoRowEncode; - tif->tif_encodestrip = _TIFFNoStripEncode; - tif->tif_encodetile = _TIFFNoTileEncode; - tif->tif_close = _TIFFvoid; - tif->tif_seek = _TIFFNoSeek; - tif->tif_cleanup = _TIFFvoid; - tif->tif_defstripsize = _TIFFDefaultStripSize; - tif->tif_deftilesize = _TIFFDefaultTileSize; - tif->tif_flags &= ~(TIFF_NOBITREV|TIFF_NOREADRAW); + tif->tif_fixuptags = _TIFFNoFixupTags; + tif->tif_decodestatus = TRUE; + tif->tif_setupdecode = _TIFFtrue; + tif->tif_predecode = _TIFFNoPreCode; + tif->tif_decoderow = _TIFFNoRowDecode; + tif->tif_decodestrip = _TIFFNoStripDecode; + tif->tif_decodetile = _TIFFNoTileDecode; + tif->tif_encodestatus = TRUE; + tif->tif_setupencode = _TIFFtrue; + tif->tif_preencode = _TIFFNoPreCode; + tif->tif_postencode = _TIFFtrue; + tif->tif_encoderow = _TIFFNoRowEncode; + tif->tif_encodestrip = _TIFFNoStripEncode; + tif->tif_encodetile = _TIFFNoTileEncode; + tif->tif_close = _TIFFvoid; + tif->tif_seek = _TIFFNoSeek; + tif->tif_cleanup = _TIFFvoid; + tif->tif_defstripsize = _TIFFDefaultStripSize; + tif->tif_deftilesize = _TIFFDefaultTileSize; + tif->tif_flags &= ~(TIFF_NOBITREV|TIFF_NOREADRAW); } int TIFFSetCompressionScheme(TIFF* tif, int scheme) { - const TIFFCodec *c = TIFFFindCODEC((uint16) scheme); + const TIFFCodec *c = TIFFFindCODEC((uint16) scheme); - _TIFFSetDefaultCompressionState(tif); - /* - * Don't treat an unknown compression scheme as an error. - * This permits applications to open files with data that - * the library does not have builtin support for, but which - * may still be meaningful. - */ - return (c ? (*c->init)(tif, scheme) : 1); + _TIFFSetDefaultCompressionState(tif); + /* + * Don't treat an unknown compression scheme as an error. + * This permits applications to open files with data that + * the library does not have builtin support for, but which + * may still be meaningful. + */ + return (c ? (*c->init)(tif, scheme) : 1); } /* @@ -178,63 +178,63 @@ TIFFSetCompressionScheme(TIFF* tif, int scheme) * by this library. */ typedef struct _codec { - struct _codec* next; - TIFFCodec* info; + struct _codec* next; + TIFFCodec* info; } codec_t; static codec_t* registeredCODECS = NULL; const TIFFCodec* TIFFFindCODEC(uint16 scheme) { - const TIFFCodec* c; - codec_t* cd; + const TIFFCodec* c; + codec_t* cd; - for (cd = registeredCODECS; cd; cd = cd->next) - if (cd->info->scheme == scheme) - return ((const TIFFCodec*) cd->info); - for (c = _TIFFBuiltinCODECS; c->name; c++) - if (c->scheme == scheme) - return (c); - return ((const TIFFCodec*) 0); + for (cd = registeredCODECS; cd; cd = cd->next) + if (cd->info->scheme == scheme) + return ((const TIFFCodec*) cd->info); + for (c = _TIFFBuiltinCODECS; c->name; c++) + if (c->scheme == scheme) + return (c); + return ((const TIFFCodec*) 0); } TIFFCodec* TIFFRegisterCODEC(uint16 scheme, const char* name, TIFFInitMethod init) { - codec_t* cd = (codec_t*) - _TIFFmalloc((tmsize_t)(sizeof (codec_t) + sizeof (TIFFCodec) + strlen(name)+1)); + codec_t* cd = (codec_t*) + _TIFFmalloc((tmsize_t)(sizeof (codec_t) + sizeof (TIFFCodec) + strlen(name)+1)); - if (cd != NULL) { - cd->info = (TIFFCodec*) ((uint8*) cd + sizeof (codec_t)); - cd->info->name = (char*) - ((uint8*) cd->info + sizeof (TIFFCodec)); - strcpy(cd->info->name, name); - cd->info->scheme = scheme; - cd->info->init = init; - cd->next = registeredCODECS; - registeredCODECS = cd; - } else { - TIFFErrorExt(0, "TIFFRegisterCODEC", - "No space to register compression scheme %s", name); - return NULL; - } - return (cd->info); + if (cd != NULL) { + cd->info = (TIFFCodec*) ((uint8*) cd + sizeof (codec_t)); + cd->info->name = (char*) + ((uint8*) cd->info + sizeof (TIFFCodec)); + strcpy(cd->info->name, name); + cd->info->scheme = scheme; + cd->info->init = init; + cd->next = registeredCODECS; + registeredCODECS = cd; + } else { + TIFFErrorExt(0, "TIFFRegisterCODEC", + "No space to register compression scheme %s", name); + return NULL; + } + return (cd->info); } void TIFFUnRegisterCODEC(TIFFCodec* c) { - codec_t* cd; - codec_t** pcd; + codec_t* cd; + codec_t** pcd; - for (pcd = ®isteredCODECS; (cd = *pcd); pcd = &cd->next) - if (cd->info == c) { - *pcd = cd->next; - _TIFFfree(cd); - return; - } - TIFFErrorExt(0, "TIFFUnRegisterCODEC", - "Cannot remove compression scheme %s; not registered", c->name); + for (pcd = ®isteredCODECS; (cd = *pcd) != NULL; pcd = &cd->next) + if (cd->info == c) { + *pcd = cd->next; + _TIFFfree(cd); + return; + } + TIFFErrorExt(0, "TIFFUnRegisterCODEC", + "Cannot remove compression scheme %s; not registered", c->name); } /************************************************************************/ @@ -244,7 +244,7 @@ TIFFUnRegisterCODEC(TIFFCodec* c) /** * Get list of configured codecs, both built-in and registered by user. * Caller is responsible to free this structure. - * + * * @return returns array of TIFFCodec records (the last record should be NULL) * or NULL if function failed. */ @@ -252,46 +252,46 @@ TIFFUnRegisterCODEC(TIFFCodec* c) TIFFCodec* TIFFGetConfiguredCODECs() { - int i = 1; - codec_t *cd; - const TIFFCodec* c; - TIFFCodec* codecs = NULL; - TIFFCodec* new_codecs; + int i = 1; + codec_t *cd; + const TIFFCodec* c; + TIFFCodec* codecs = NULL; + TIFFCodec* new_codecs; - for (cd = registeredCODECS; cd; cd = cd->next) { - new_codecs = (TIFFCodec *) - _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); - if (!new_codecs) { - _TIFFfree (codecs); - return NULL; - } - codecs = new_codecs; - _TIFFmemcpy(codecs + i - 1, cd, sizeof(TIFFCodec)); - i++; - } - for (c = _TIFFBuiltinCODECS; c->name; c++) { - if (TIFFIsCODECConfigured(c->scheme)) { - new_codecs = (TIFFCodec *) - _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); - if (!new_codecs) { - _TIFFfree (codecs); - return NULL; - } - codecs = new_codecs; - _TIFFmemcpy(codecs + i - 1, (const void*)c, sizeof(TIFFCodec)); - i++; - } - } + for (cd = registeredCODECS; cd; cd = cd->next) { + new_codecs = (TIFFCodec *) + _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); + if (!new_codecs) { + _TIFFfree (codecs); + return NULL; + } + codecs = new_codecs; + _TIFFmemcpy(codecs + i - 1, cd, sizeof(TIFFCodec)); + i++; + } + for (c = _TIFFBuiltinCODECS; c->name; c++) { + if (TIFFIsCODECConfigured(c->scheme)) { + new_codecs = (TIFFCodec *) + _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); + if (!new_codecs) { + _TIFFfree (codecs); + return NULL; + } + codecs = new_codecs; + _TIFFmemcpy(codecs + i - 1, (const void*)c, sizeof(TIFFCodec)); + i++; + } + } - new_codecs = (TIFFCodec *) _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); - if (!new_codecs) { - _TIFFfree (codecs); - return NULL; - } - codecs = new_codecs; - _TIFFmemset(codecs + i - 1, 0, sizeof(TIFFCodec)); + new_codecs = (TIFFCodec *) _TIFFrealloc(codecs, i * sizeof(TIFFCodec)); + if (!new_codecs) { + _TIFFfree (codecs); + return NULL; + } + codecs = new_codecs; + _TIFFmemset(codecs + i - 1, 0, sizeof(TIFFCodec)); - return codecs; + return codecs; } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_config.h.cmake.in b/3rdparty/libtiff/tif_config.h.cmake.in new file mode 100644 index 0000000000..de0f3a3c2c --- /dev/null +++ b/3rdparty/libtiff/tif_config.h.cmake.in @@ -0,0 +1,261 @@ +/* libtiff/tif_config.h.cmake.in. Not generated, but originated from autoheader. */ +/* This file must be kept up-to-date with needed substitutions from libtiff/tif_config.h.in. */ + +/* Support CCITT Group 3 & 4 algorithms */ +#cmakedefine CCITT_SUPPORT 1 + +/* Pick up YCbCr subsampling info from the JPEG data stream to support files + lacking the tag (default enabled). */ +#cmakedefine CHECK_JPEG_YCBCR_SUBSAMPLING 1 + +/* enable partial strip reading for large strips (experimental) */ +#cmakedefine CHUNKY_STRIP_READ_SUPPORT 1 + +/* Support C++ stream API (requires C++ compiler) */ +#cmakedefine CXX_SUPPORT 1 + +/* enable deferred strip/tile offset/size loading (experimental) */ +#cmakedefine DEFER_STRILE_LOAD 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ASSERT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `floor' function. */ +#cmakedefine HAVE_FLOOR 1 + +/* Define to 1 if you have the `getopt' function. */ +#cmakedefine HAVE_GETOPT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GLUT_GLUT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GL_GLUT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GL_GLU_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GL_GL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IO_H 1 + +/* Define to 1 if you have the `isascii' function. */ +#cmakedefine HAVE_ISASCII 1 + +/* Define to 1 if you have the `jbg_newlen' function. */ +#cmakedefine HAVE_JBG_NEWLEN 1 + +/* Define to 1 if you have the `lfind' function. */ +#cmakedefine HAVE_LFIND 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MALLOC_H 1 + +/* Define to 1 if you have the `memmove' function. */ +#cmakedefine HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `memset' function. */ +#cmakedefine HAVE_MEMSET 1 + +/* Define to 1 if you have the `mmap' function. */ +#cmakedefine HAVE_MMAP 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENGL_GLU_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENGL_GL_H 1 + +/* Define to 1 if you have the `pow' function. */ +#cmakedefine HAVE_POW 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SEARCH_H 1 + +/* Define to 1 if you have the `setmode' function. */ +#cmakedefine HAVE_SETMODE 1 + +/* Define to 1 if you have the `snprintf' function. */ +#cmakedefine HAVE_SNPRINTF 1 + +/* Define to 1 if you have the `sqrt' function. */ +#cmakedefine HAVE_SQRT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#cmakedefine HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strchr' function. */ +#cmakedefine HAVE_STRCHR 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the `strrchr' function. */ +#cmakedefine HAVE_STRRCHR 1 + +/* Define to 1 if you have the `strstr' function. */ +#cmakedefine HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtol' function. */ +#cmakedefine HAVE_STRTOL 1 + +/* Define to 1 if you have the `strtoul' function. */ +#cmakedefine HAVE_STRTOUL 1 + +/* Define to 1 if you have the `strtoull' function. */ +#cmakedefine HAVE_STRTOULL 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* 8/12 bit libjpeg dual mode enabled */ +#cmakedefine JPEG_DUAL_MODE_8_12 1 + +/* 12bit libjpeg primary include file with path */ +#define LIBJPEG_12_PATH @LIBJPEG_12_PATH@ + +/* Support LZMA2 compression */ +#cmakedefine LZMA_SUPPORT 1 + +/* Name of package */ +#define PACKAGE "@PACKAGE_NAME@" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@PACKAGE_NAME@" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "@PACKAGE_STRING@" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "@PACKAGE_TARNAME@" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "@PACKAGE_URL@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* The size of `signed int', as computed by sizeof. */ +#define SIZEOF_SIGNED_INT @SIZEOF_SIGNED_INT@ + +/* The size of `signed long', as computed by sizeof. */ +#define SIZEOF_SIGNED_LONG @SIZEOF_SIGNED_LONG@ + +/* The size of `signed long long', as computed by sizeof. */ +#define SIZEOF_SIGNED_LONG_LONG @SIZEOF_SIGNED_LONG_LONG@ + +/* The size of `signed short', as computed by sizeof. */ +#define SIZEOF_SIGNED_SHORT @SIZEOF_SIGNED_SHORT@ + +/* The size of `unsigned char *', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_CHAR_P @SIZEOF_UNSIGNED_CHAR_P@ + +/* The size of `unsigned int', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_INT @SIZEOF_UNSIGNED_INT@ + +/* The size of `unsigned long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG @SIZEOF_UNSIGNED_LONG@ + +/* The size of `unsigned long long', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_LONG_LONG @SIZEOF_UNSIGNED_LONG_LONG@ + +/* The size of `unsigned short', as computed by sizeof. */ +#define SIZEOF_UNSIGNED_SHORT @SIZEOF_UNSIGNED_SHORT@ + +/* Default size of the strip in bytes (when strip chopping enabled) */ +#define STRIP_SIZE_DEFAULT @STRIP_SIZE_DEFAULT@ + +/* Signed 32-bit type formatter */ +#define TIFF_INT32_FORMAT "@TIFF_INT32_FORMAT@" + +/* Signed 64-bit type formatter */ +#define TIFF_INT64_FORMAT "@TIFF_INT64_FORMAT@" + +/* Pointer difference type formatter */ +#define TIFF_PTRDIFF_FORMAT "@TIFF_PTRDIFF_FORMAT@" + +/* Unsigned size type formatter */ +#define TIFF_SIZE_FORMAT "@TIFF_SIZE_FORMAT@" + +/* Signed size type formatter */ +#define TIFF_SSIZE_FORMAT "@TIFF_SSIZE_FORMAT@" + +/* Unsigned 32-bit type formatter */ +#define TIFF_UINT32_FORMAT "@TIFF_UINT32_FORMAT@" + +/* Unsigned 64-bit type formatter */ +#define TIFF_UINT64_FORMAT "@TIFF_UINT64_FORMAT@" + +/* Unsigned 8-bit type */ +#define TIFF_UINT8_T @TIFF_UINT8_T@ + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your declares `struct tm'. */ +#cmakedefine TM_IN_SYS_TIME 1 + +/* define to use win32 IO system */ +#cmakedefine USE_WIN32_FILEIO 1 + +/* Version number of package */ +#define VERSION "@PACKAGE_VERSION@" + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS @FILE_OFFSET_BITS@ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#define inline @INLINE_KEYWORD@ +#endif + +/* Define to `long int' if does not define. */ +#undef off_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t diff --git a/3rdparty/libtiff/tif_config.h.cmakein b/3rdparty/libtiff/tif_config.h.cmakein deleted file mode 100644 index 24f58119ba..0000000000 --- a/3rdparty/libtiff/tif_config.h.cmakein +++ /dev/null @@ -1,162 +0,0 @@ -/* libtiff/tif_config.h. Generated from tif_config.h.in by configure. */ -/* libtiff/tif_config.h.in. Generated from configure.ac by autoheader. */ - -/* Support CCITT Group 3 & 4 algorithms */ -#define CCITT_SUPPORT 1 - -/* Pick up YCbCr subsampling info from the JPEG data stream to support files - lacking the tag (default enabled). */ -#define CHECK_JPEG_YCBCR_SUBSAMPLING 1 - -/* enable partial strip reading for large strips (experimental) */ -#undef CHUNKY_STRIP_READ_SUPPORT - -/* Treat extra sample as alpha (default enabled). The RGBA interface will - treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many - packages produce RGBA files but don't mark the alpha properly. */ -#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1 - -/* enable deferred strip/tile offset/size loading (experimental) */ -#undef DEFER_STRILE_LOAD - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_ASSERT_H - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_FCNTL_H - -/* Define as 0 or 1 according to the floating point format suported by the - machine */ -#define HAVE_IEEEFP 1 - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_IO_H - -/* Define to 1 if you have the `jbg_newlen' function. */ -#cmakedefine HAVE_JBG_NEWLEN - -/* Define to 1 if you have the `mmap' function. */ -#cmakedefine HAVE_MMAP - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SEARCH_H - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_STRING_H - -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#ifndef HAVE_UNISTD_H -#cmakedefine HAVE_UNISTD_H -#endif - -/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian - (Intel) */ -#define HOST_BIGENDIAN @WORDS_BIGENDIAN@ - -/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */ -#define HOST_FILLORDER FILLORDER_LSB2MSB - -/* Support ISO JBIG compression (requires JBIG-KIT library) */ -#undef JBIG_SUPPORT - -/* 8/12 bit libjpeg dual mode enabled */ -/* #undef JPEG_DUAL_MODE_8_12 */ - -/* Support JPEG compression (requires IJG JPEG library) */ -#undef JPEG_SUPPORT - -/* 12bit libjpeg primary include file with path */ -/* #undef LIBJPEG_12_PATH */ - -/* Support LogLuv high dynamic range encoding */ -#define LOGLUV_SUPPORT 1 - -/* Support LZMA2 compression */ -/* #undef LZMA_SUPPORT */ - -/* Support LZW algorithm */ -#define LZW_SUPPORT 1 - -/* Support Microsoft Document Imaging format */ -#define MDI_SUPPORT 1 - -/* Support NeXT 2-bit RLE algorithm */ -#define NEXT_SUPPORT 1 - -/* Support Old JPEG compresson (read-only) */ -#undef OJPEG_SUPPORT - -/* Support Macintosh PackBits algorithm */ -#define PACKBITS_SUPPORT 1 - -/* Support Pixar log-format algorithm (requires Zlib) */ -#define PIXARLOG_SUPPORT 1 - -/* The size of `unsigned long', as computed by sizeof. */ -#define SIZEOF_UNSIGNED_LONG 8 - -/* Support strip chopping (whether or not to convert single-strip uncompressed - images to mutiple strips of specified size to reduce memory usage) */ -#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP - -/* Default size of the strip in bytes (when strip chopping enabled) */ -//#define STRIP_SIZE_DEFAULT 8192 - -/* Support ThunderScan 4-bit RLE algorithm */ -#define THUNDER_SUPPORT 1 - -/* Signed 8-bit type */ -#define TIFF_INT8_T signed char - -/* Signed 16-bit type */ -#define TIFF_INT16_T signed short - -/* Signed 32-bit type */ -#define TIFF_INT32_T signed int - -/* Signed size type */ -#define TIFF_SSIZE_T size_t - -/* Unsigned 8-bit type */ -#define TIFF_UINT8_T unsigned char - -/* Unsigned 16-bit type */ -#define TIFF_UINT16_T unsigned short - -/* Unsigned 32-bit type */ -#define TIFF_UINT32_T unsigned int - -#ifdef _MSC_VER -/* Signed 64-bit type */ -# define TIFF_INT64_T signed __int64 -/* Unsigned 64-bit type */ -# define TIFF_UINT64_T unsigned __int64 -#else -/* Signed 64-bit type */ -# define TIFF_INT64_T long long -/* Signed 64-bit type */ -# define TIFF_UINT64_T unsigned long long -#endif - -/* Signed 64-bit type formatter */ -/* Unsigned 64-bit type formatter */ -#if defined _MSC_VER || defined __MINGW__ || defined __MINGW32__ -# define TIFF_UINT64_FORMAT "%I64u" -# define TIFF_SSIZE_FORMAT "%Iu" -#else -# define TIFF_UINT64_FORMAT "%llu" -# define TIFF_SSIZE_FORMAT "%zd" -#endif - -/* define to use win32 IO system */ -#cmakedefine USE_WIN32_FILEIO - -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#cmakedefine WORDS_BIGENDIAN 1 - -/* Support Deflate compression */ -#define ZIP_SUPPORT 1 diff --git a/3rdparty/libtiff/tif_dir.c b/3rdparty/libtiff/tif_dir.c index 8ddcea2a8d..f00f8080a2 100644 --- a/3rdparty/libtiff/tif_dir.c +++ b/3rdparty/libtiff/tif_dir.c @@ -1,26 +1,26 @@ -/* $Id: tif_dir.c,v 1.113 2012-06-14 20:32:53 fwarmerdam Exp $ */ +/* $Id: tif_dir.c,v 1.131 2017-07-11 21:38:04 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -31,6 +31,7 @@ * (and also some miscellaneous stuff) */ #include "tiffiop.h" +#include /* * These are used in the backwards compatibility code... @@ -43,27 +44,29 @@ static void setByteArray(void** vpp, void* vp, size_t nmemb, size_t elem_size) { - if (*vpp) - _TIFFfree(*vpp), *vpp = 0; - if (vp) { - tmsize_t bytes = (tmsize_t)(nmemb * elem_size); - if (elem_size && bytes / elem_size == nmemb) - *vpp = (void*) _TIFFmalloc(bytes); - if (*vpp) - _TIFFmemcpy(*vpp, vp, bytes); - } + if (*vpp) { + _TIFFfree(*vpp); + *vpp = 0; + } + if (vp) { + tmsize_t bytes = (tmsize_t)(nmemb * elem_size); + if (elem_size && bytes / elem_size == nmemb) + *vpp = (void*) _TIFFmalloc(bytes); + if (*vpp) + _TIFFmemcpy(*vpp, vp, bytes); + } } void _TIFFsetByteArray(void** vpp, void* vp, uint32 n) { setByteArray(vpp, vp, n, 1); } void _TIFFsetString(char** cpp, char* cp) { setByteArray((void**) cpp, (void*) cp, strlen(cp)+1, 1); } -void _TIFFsetNString(char** cpp, char* cp, uint32 n) +static void _TIFFsetNString(char** cpp, char* cp, uint32 n) { setByteArray((void**) cpp, (void*) cp, n, 1); } void _TIFFsetShortArray(uint16** wpp, uint16* wp, uint32 n) { setByteArray((void**) wpp, (void*) wp, n, sizeof (uint16)); } void _TIFFsetLongArray(uint32** lpp, uint32* lp, uint32 n) { setByteArray((void**) lpp, (void*) lp, n, sizeof (uint32)); } -void _TIFFsetLong8Array(uint64** lpp, uint64* lp, uint32 n) +static void _TIFFsetLong8Array(uint64** lpp, uint64* lp, uint32 n) { setByteArray((void**) lpp, (void*) lp, n, sizeof (uint64)); } void _TIFFsetFloatArray(float** fpp, float* fp, uint32 n) { setByteArray((void**) fpp, (void*) fp, n, sizeof (float)); } @@ -73,14 +76,14 @@ void _TIFFsetDoubleArray(double** dpp, double* dp, uint32 n) static void setDoubleArrayOneValue(double** vpp, double value, size_t nmemb) { - if (*vpp) - _TIFFfree(*vpp); - *vpp = _TIFFmalloc(nmemb*sizeof(double)); - if (*vpp) - { - while (nmemb--) - ((double*)*vpp)[nmemb] = value; - } + if (*vpp) + _TIFFfree(*vpp); + *vpp = _TIFFmalloc(nmemb*sizeof(double)); + if (*vpp) + { + while (nmemb--) + ((double*)*vpp)[nmemb] = value; + } } /* @@ -90,606 +93,655 @@ static int setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v) { /* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */ -#define EXTRASAMPLE_COREL_UNASSALPHA 999 +#define EXTRASAMPLE_COREL_UNASSALPHA 999 - uint16* va; - uint32 i; + uint16* va; + uint32 i; - *v = (uint16) va_arg(ap, uint16_vap); - if ((uint16) *v > td->td_samplesperpixel) - return 0; - va = va_arg(ap, uint16*); - if (*v > 0 && va == NULL) /* typically missing param */ - return 0; - for (i = 0; i < *v; i++) { - if (va[i] > EXTRASAMPLE_UNASSALPHA) { - /* - * XXX: Corel Draw is known to produce incorrect - * ExtraSamples tags which must be patched here if we - * want to be able to open some of the damaged TIFF - * files: - */ - if (va[i] == EXTRASAMPLE_COREL_UNASSALPHA) - va[i] = EXTRASAMPLE_UNASSALPHA; - else - return 0; - } - } - td->td_extrasamples = (uint16) *v; - _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples); - return 1; + *v = (uint16) va_arg(ap, uint16_vap); + if ((uint16) *v > td->td_samplesperpixel) + return 0; + va = va_arg(ap, uint16*); + if (*v > 0 && va == NULL) /* typically missing param */ + return 0; + for (i = 0; i < *v; i++) { + if (va[i] > EXTRASAMPLE_UNASSALPHA) { + /* + * XXX: Corel Draw is known to produce incorrect + * ExtraSamples tags which must be patched here if we + * want to be able to open some of the damaged TIFF + * files: + */ + if (va[i] == EXTRASAMPLE_COREL_UNASSALPHA) + va[i] = EXTRASAMPLE_UNASSALPHA; + else + return 0; + } + } + td->td_extrasamples = (uint16) *v; + _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples); + return 1; #undef EXTRASAMPLE_COREL_UNASSALPHA } /* - * Confirm we have "samplesperpixel" ink names separated by \0. Returns + * Confirm we have "samplesperpixel" ink names separated by \0. Returns * zero if the ink names are not as expected. */ static uint32 checkInkNamesString(TIFF* tif, uint32 slen, const char* s) { - TIFFDirectory* td = &tif->tif_dir; - uint16 i = td->td_samplesperpixel; + TIFFDirectory* td = &tif->tif_dir; + uint16 i = td->td_samplesperpixel; - if (slen > 0) { - const char* ep = s+slen; - const char* cp = s; - for (; i > 0; i--) { - for (; cp < ep && *cp != '\0'; cp++) {} - if (cp >= ep) - goto bad; - cp++; /* skip \0 */ - } - return ((uint32)(cp-s)); - } + if (slen > 0) { + const char* ep = s+slen; + const char* cp = s; + for (; i > 0; i--) { + for (; cp < ep && *cp != '\0'; cp++) {} + if (cp >= ep) + goto bad; + cp++; /* skip \0 */ + } + return ((uint32)(cp-s)); + } bad: - TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", - "%s: Invalid InkNames value; expecting %d names, found %d", - tif->tif_name, - td->td_samplesperpixel, - td->td_samplesperpixel-i); - return (0); + TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", + "%s: Invalid InkNames value; expecting %d names, found %d", + tif->tif_name, + td->td_samplesperpixel, + td->td_samplesperpixel-i); + return (0); +} + +static float TIFFClampDoubleToFloat( double val ) +{ + if( val > FLT_MAX ) + return FLT_MAX; + if( val < -FLT_MAX ) + return -FLT_MAX; + return (float)val; } static int _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) { - static const char module[] = "_TIFFVSetField"; + static const char module[] = "_TIFFVSetField"; - TIFFDirectory* td = &tif->tif_dir; - int status = 1; - uint32 v32, i, v; - char* s; - const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY); - uint32 standard_tag = tag; + TIFFDirectory* td = &tif->tif_dir; + int status = 1; + uint32 v32, i, v; + double dblval; + char* s; + const TIFFField *fip = TIFFFindField(tif, tag, TIFF_ANY); + uint32 standard_tag = tag; + if( fip == NULL ) /* cannot happen since OkToChangeTag() already checks it */ + return 0; + /* + * We want to force the custom code to be used for custom + * fields even if the tag happens to match a well known + * one - important for reinterpreted handling of standard + * tag values in custom directories (i.e. EXIF) + */ + if (fip->field_bit == FIELD_CUSTOM) { + standard_tag = 0; + } - /* - * We want to force the custom code to be used for custom - * fields even if the tag happens to match a well known - * one - important for reinterpreted handling of standard - * tag values in custom directories (ie. EXIF) - */ - if (fip->field_bit == FIELD_CUSTOM) { - standard_tag = 0; - } - - switch (standard_tag) { - case TIFFTAG_SUBFILETYPE: - td->td_subfiletype = (uint32) va_arg(ap, uint32); - break; - case TIFFTAG_IMAGEWIDTH: - td->td_imagewidth = (uint32) va_arg(ap, uint32); - break; - case TIFFTAG_IMAGELENGTH: - td->td_imagelength = (uint32) va_arg(ap, uint32); - break; - case TIFFTAG_BITSPERSAMPLE: - td->td_bitspersample = (uint16) va_arg(ap, uint16_vap); - /* - * If the data require post-decoding processing to byte-swap - * samples, set it up here. Note that since tags are required - * to be ordered, compression code can override this behaviour - * in the setup method if it wants to roll the post decoding - * work in with its normal work. - */ - if (tif->tif_flags & TIFF_SWAB) { - if (td->td_bitspersample == 8) - tif->tif_postdecode = _TIFFNoPostDecode; - else if (td->td_bitspersample == 16) - tif->tif_postdecode = _TIFFSwab16BitData; - else if (td->td_bitspersample == 24) - tif->tif_postdecode = _TIFFSwab24BitData; - else if (td->td_bitspersample == 32) - tif->tif_postdecode = _TIFFSwab32BitData; - else if (td->td_bitspersample == 64) - tif->tif_postdecode = _TIFFSwab64BitData; - else if (td->td_bitspersample == 128) /* two 64's */ - tif->tif_postdecode = _TIFFSwab64BitData; - } - break; - case TIFFTAG_COMPRESSION: - v = (uint16) va_arg(ap, uint16_vap); - /* - * If we're changing the compression scheme, the notify the - * previous module so that it can cleanup any state it's - * setup. - */ - if (TIFFFieldSet(tif, FIELD_COMPRESSION)) { - if ((uint32)td->td_compression == v) - break; - (*tif->tif_cleanup)(tif); - tif->tif_flags &= ~TIFF_CODERSETUP; - } - /* - * Setup new compression routine state. - */ - if( (status = TIFFSetCompressionScheme(tif, v)) != 0 ) - td->td_compression = (uint16) v; - else - status = 0; - break; - case TIFFTAG_PHOTOMETRIC: - td->td_photometric = (uint16) va_arg(ap, uint16_vap); - break; - case TIFFTAG_THRESHHOLDING: - td->td_threshholding = (uint16) va_arg(ap, uint16_vap); - break; - case TIFFTAG_FILLORDER: - v = (uint16) va_arg(ap, uint16_vap); - if (v != FILLORDER_LSB2MSB && v != FILLORDER_MSB2LSB) - goto badvalue; - td->td_fillorder = (uint16) v; - break; - case TIFFTAG_ORIENTATION: - v = (uint16) va_arg(ap, uint16_vap); - if (v < ORIENTATION_TOPLEFT || ORIENTATION_LEFTBOT < v) - goto badvalue; - else - td->td_orientation = (uint16) v; - break; - case TIFFTAG_SAMPLESPERPIXEL: - v = (uint16) va_arg(ap, uint16_vap); - if (v == 0) - goto badvalue; - td->td_samplesperpixel = (uint16) v; - break; - case TIFFTAG_ROWSPERSTRIP: - v32 = (uint32) va_arg(ap, uint32); - if (v32 == 0) - goto badvalue32; - td->td_rowsperstrip = v32; - if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { - td->td_tilelength = v32; - td->td_tilewidth = td->td_imagewidth; - } - break; - case TIFFTAG_MINSAMPLEVALUE: - td->td_minsamplevalue = (uint16) va_arg(ap, uint16_vap); - break; - case TIFFTAG_MAXSAMPLEVALUE: - td->td_maxsamplevalue = (uint16) va_arg(ap, uint16_vap); - break; - case TIFFTAG_SMINSAMPLEVALUE: - if (tif->tif_flags & TIFF_PERSAMPLE) - _TIFFsetDoubleArray(&td->td_sminsamplevalue, va_arg(ap, double*), td->td_samplesperpixel); - else - setDoubleArrayOneValue(&td->td_sminsamplevalue, va_arg(ap, double), td->td_samplesperpixel); - break; - case TIFFTAG_SMAXSAMPLEVALUE: - if (tif->tif_flags & TIFF_PERSAMPLE) - _TIFFsetDoubleArray(&td->td_smaxsamplevalue, va_arg(ap, double*), td->td_samplesperpixel); - else - setDoubleArrayOneValue(&td->td_smaxsamplevalue, va_arg(ap, double), td->td_samplesperpixel); - break; - case TIFFTAG_XRESOLUTION: - td->td_xresolution = (float) va_arg(ap, double); - break; - case TIFFTAG_YRESOLUTION: - td->td_yresolution = (float) va_arg(ap, double); - break; - case TIFFTAG_PLANARCONFIG: - v = (uint16) va_arg(ap, uint16_vap); - if (v != PLANARCONFIG_CONTIG && v != PLANARCONFIG_SEPARATE) - goto badvalue; - td->td_planarconfig = (uint16) v; - break; - case TIFFTAG_XPOSITION: - td->td_xposition = (float) va_arg(ap, double); - break; - case TIFFTAG_YPOSITION: - td->td_yposition = (float) va_arg(ap, double); - break; - case TIFFTAG_RESOLUTIONUNIT: - v = (uint16) va_arg(ap, uint16_vap); - if (v < RESUNIT_NONE || RESUNIT_CENTIMETER < v) - goto badvalue; - td->td_resolutionunit = (uint16) v; - break; - case TIFFTAG_PAGENUMBER: - td->td_pagenumber[0] = (uint16) va_arg(ap, uint16_vap); - td->td_pagenumber[1] = (uint16) va_arg(ap, uint16_vap); - break; - case TIFFTAG_HALFTONEHINTS: - td->td_halftonehints[0] = (uint16) va_arg(ap, uint16_vap); - td->td_halftonehints[1] = (uint16) va_arg(ap, uint16_vap); - break; - case TIFFTAG_COLORMAP: - v32 = (uint32)(1L<td_bitspersample); - _TIFFsetShortArray(&td->td_colormap[0], va_arg(ap, uint16*), v32); - _TIFFsetShortArray(&td->td_colormap[1], va_arg(ap, uint16*), v32); - _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32); - break; - case TIFFTAG_EXTRASAMPLES: - if (!setExtraSamples(td, ap, &v)) - goto badvalue; - break; - case TIFFTAG_MATTEING: - td->td_extrasamples = (((uint16) va_arg(ap, uint16_vap)) != 0); - if (td->td_extrasamples) { - uint16 sv = EXTRASAMPLE_ASSOCALPHA; - _TIFFsetShortArray(&td->td_sampleinfo, &sv, 1); - } - break; - case TIFFTAG_TILEWIDTH: - v32 = (uint32) va_arg(ap, uint32); - if (v32 % 16) { - if (tif->tif_mode != O_RDONLY) - goto badvalue32; - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, - "Nonstandard tile width %d, convert file", v32); - } - td->td_tilewidth = v32; - tif->tif_flags |= TIFF_ISTILED; - break; - case TIFFTAG_TILELENGTH: - v32 = (uint32) va_arg(ap, uint32); - if (v32 % 16) { - if (tif->tif_mode != O_RDONLY) - goto badvalue32; - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, - "Nonstandard tile length %d, convert file", v32); - } - td->td_tilelength = v32; - tif->tif_flags |= TIFF_ISTILED; - break; - case TIFFTAG_TILEDEPTH: - v32 = (uint32) va_arg(ap, uint32); - if (v32 == 0) - goto badvalue32; - td->td_tiledepth = v32; - break; - case TIFFTAG_DATATYPE: - v = (uint16) va_arg(ap, uint16_vap); - switch (v) { - case DATATYPE_VOID: v = SAMPLEFORMAT_VOID; break; - case DATATYPE_INT: v = SAMPLEFORMAT_INT; break; - case DATATYPE_UINT: v = SAMPLEFORMAT_UINT; break; - case DATATYPE_IEEEFP: v = SAMPLEFORMAT_IEEEFP;break; - default: goto badvalue; - } - td->td_sampleformat = (uint16) v; - break; - case TIFFTAG_SAMPLEFORMAT: - v = (uint16) va_arg(ap, uint16_vap); - if (v < SAMPLEFORMAT_UINT || SAMPLEFORMAT_COMPLEXIEEEFP < v) - goto badvalue; - td->td_sampleformat = (uint16) v; - - /* Try to fix up the SWAB function for complex data. */ - if( td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT - && td->td_bitspersample == 32 - && tif->tif_postdecode == _TIFFSwab32BitData ) - tif->tif_postdecode = _TIFFSwab16BitData; - else if( (td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT - || td->td_sampleformat == SAMPLEFORMAT_COMPLEXIEEEFP) - && td->td_bitspersample == 64 - && tif->tif_postdecode == _TIFFSwab64BitData ) - tif->tif_postdecode = _TIFFSwab32BitData; - break; - case TIFFTAG_IMAGEDEPTH: - td->td_imagedepth = (uint32) va_arg(ap, uint32); - break; - case TIFFTAG_SUBIFD: - if ((tif->tif_flags & TIFF_INSUBIFD) == 0) { - td->td_nsubifd = (uint16) va_arg(ap, uint16_vap); - _TIFFsetLong8Array(&td->td_subifd, (uint64*) va_arg(ap, uint64*), - (long) td->td_nsubifd); - } else { - TIFFErrorExt(tif->tif_clientdata, module, - "%s: Sorry, cannot nest SubIFDs", - tif->tif_name); - status = 0; - } - break; - case TIFFTAG_YCBCRPOSITIONING: - td->td_ycbcrpositioning = (uint16) va_arg(ap, uint16_vap); - break; - case TIFFTAG_YCBCRSUBSAMPLING: - td->td_ycbcrsubsampling[0] = (uint16) va_arg(ap, uint16_vap); - td->td_ycbcrsubsampling[1] = (uint16) va_arg(ap, uint16_vap); - break; - case TIFFTAG_TRANSFERFUNCTION: - v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1; - for (i = 0; i < v; i++) - _TIFFsetShortArray(&td->td_transferfunction[i], - va_arg(ap, uint16*), 1L<td_bitspersample); - break; - case TIFFTAG_REFERENCEBLACKWHITE: - /* XXX should check for null range */ - _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6); - break; - case TIFFTAG_INKNAMES: - v = (uint16) va_arg(ap, uint16_vap); - s = va_arg(ap, char*); - v = checkInkNamesString(tif, v, s); - status = v > 0; - if( v > 0 ) { - _TIFFsetNString(&td->td_inknames, s, v); - td->td_inknameslen = v; - } - break; - case TIFFTAG_PERSAMPLE: - v = (uint16) va_arg(ap, uint16_vap); - if( v == PERSAMPLE_MULTI ) - tif->tif_flags |= TIFF_PERSAMPLE; - else - tif->tif_flags &= ~TIFF_PERSAMPLE; - break; - default: { - TIFFTagValue *tv; - int tv_size, iCustom; - - /* - * This can happen if multiple images are open with different - * codecs which have private tags. The global tag information - * table may then have tags that are valid for one file but not - * the other. If the client tries to set a tag that is not valid - * for the image's codec then we'll arrive here. This - * happens, for example, when tiffcp is used to convert between - * compression schemes and codec-specific tags are blindly copied. - */ - if(fip == NULL || fip->field_bit != FIELD_CUSTOM) { - TIFFErrorExt(tif->tif_clientdata, module, - "%s: Invalid %stag \"%s\" (not supported by codec)", - tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", - fip ? fip->field_name : "Unknown"); - status = 0; - break; - } - - /* - * Find the existing entry for this custom value. - */ - tv = NULL; - for (iCustom = 0; iCustom < td->td_customValueCount; iCustom++) { - if (td->td_customValues[iCustom].info->field_tag == tag) { - tv = td->td_customValues + iCustom; - if (tv->value != NULL) { - _TIFFfree(tv->value); - tv->value = NULL; - } - break; - } - } - - /* - * Grow the custom list if the entry was not found. - */ - if(tv == NULL) { - TIFFTagValue *new_customValues; - - td->td_customValueCount++; - new_customValues = (TIFFTagValue *) - _TIFFrealloc(td->td_customValues, - sizeof(TIFFTagValue) * td->td_customValueCount); - if (!new_customValues) { - TIFFErrorExt(tif->tif_clientdata, module, - "%s: Failed to allocate space for list of custom values", - tif->tif_name); - status = 0; - goto end; - } - - td->td_customValues = new_customValues; - - tv = td->td_customValues + (td->td_customValueCount - 1); - tv->info = fip; - tv->value = NULL; - tv->count = 0; - } - - /* - * Set custom value ... save a copy of the custom tag value. - */ - tv_size = _TIFFDataSize(fip->field_type); - if (tv_size == 0) { - status = 0; - TIFFErrorExt(tif->tif_clientdata, module, - "%s: Bad field type %d for \"%s\"", - tif->tif_name, fip->field_type, - fip->field_name); - goto end; - } - - if (fip->field_type == TIFF_ASCII) + switch (standard_tag) { + case TIFFTAG_SUBFILETYPE: + td->td_subfiletype = (uint32) va_arg(ap, uint32); + break; + case TIFFTAG_IMAGEWIDTH: + td->td_imagewidth = (uint32) va_arg(ap, uint32); + break; + case TIFFTAG_IMAGELENGTH: + td->td_imagelength = (uint32) va_arg(ap, uint32); + break; + case TIFFTAG_BITSPERSAMPLE: + td->td_bitspersample = (uint16) va_arg(ap, uint16_vap); + /* + * If the data require post-decoding processing to byte-swap + * samples, set it up here. Note that since tags are required + * to be ordered, compression code can override this behaviour + * in the setup method if it wants to roll the post decoding + * work in with its normal work. + */ + if (tif->tif_flags & TIFF_SWAB) { + if (td->td_bitspersample == 8) + tif->tif_postdecode = _TIFFNoPostDecode; + else if (td->td_bitspersample == 16) + tif->tif_postdecode = _TIFFSwab16BitData; + else if (td->td_bitspersample == 24) + tif->tif_postdecode = _TIFFSwab24BitData; + else if (td->td_bitspersample == 32) + tif->tif_postdecode = _TIFFSwab32BitData; + else if (td->td_bitspersample == 64) + tif->tif_postdecode = _TIFFSwab64BitData; + else if (td->td_bitspersample == 128) /* two 64's */ + tif->tif_postdecode = _TIFFSwab64BitData; + } + break; + case TIFFTAG_COMPRESSION: + v = (uint16) va_arg(ap, uint16_vap); + /* + * If we're changing the compression scheme, the notify the + * previous module so that it can cleanup any state it's + * setup. + */ + if (TIFFFieldSet(tif, FIELD_COMPRESSION)) { + if ((uint32)td->td_compression == v) + break; + (*tif->tif_cleanup)(tif); + tif->tif_flags &= ~TIFF_CODERSETUP; + } + /* + * Setup new compression routine state. + */ + if( (status = TIFFSetCompressionScheme(tif, v)) != 0 ) + td->td_compression = (uint16) v; + else + status = 0; + break; + case TIFFTAG_PHOTOMETRIC: + td->td_photometric = (uint16) va_arg(ap, uint16_vap); + break; + case TIFFTAG_THRESHHOLDING: + td->td_threshholding = (uint16) va_arg(ap, uint16_vap); + break; + case TIFFTAG_FILLORDER: + v = (uint16) va_arg(ap, uint16_vap); + if (v != FILLORDER_LSB2MSB && v != FILLORDER_MSB2LSB) + goto badvalue; + td->td_fillorder = (uint16) v; + break; + case TIFFTAG_ORIENTATION: + v = (uint16) va_arg(ap, uint16_vap); + if (v < ORIENTATION_TOPLEFT || ORIENTATION_LEFTBOT < v) + goto badvalue; + else + td->td_orientation = (uint16) v; + break; + case TIFFTAG_SAMPLESPERPIXEL: + v = (uint16) va_arg(ap, uint16_vap); + if (v == 0) + goto badvalue; + if( v != td->td_samplesperpixel ) { - uint32 ma; - char* mb; - if (fip->field_passcount) + /* See http://bugzilla.maptools.org/show_bug.cgi?id=2500 */ + if( td->td_sminsamplevalue != NULL ) { - assert(fip->field_writecount==TIFF_VARIABLE2); - ma=(uint32)va_arg(ap,uint32); - mb=(char*)va_arg(ap,char*); + TIFFWarningExt(tif->tif_clientdata,module, + "SamplesPerPixel tag value is changing, " + "but SMinSampleValue tag was read with a different value. Cancelling it"); + TIFFClrFieldBit(tif,FIELD_SMINSAMPLEVALUE); + _TIFFfree(td->td_sminsamplevalue); + td->td_sminsamplevalue = NULL; } - else + if( td->td_smaxsamplevalue != NULL ) { - mb=(char*)va_arg(ap,char*); - ma=(uint32)(strlen(mb)+1); - } - tv->count=ma; - setByteArray(&tv->value,mb,ma,1); - } - else - { - if (fip->field_passcount) { - if (fip->field_writecount == TIFF_VARIABLE2) - tv->count = (uint32) va_arg(ap, uint32); - else - tv->count = (int) va_arg(ap, int); - } else if (fip->field_writecount == TIFF_VARIABLE - || fip->field_writecount == TIFF_VARIABLE2) - tv->count = 1; - else if (fip->field_writecount == TIFF_SPP) - tv->count = td->td_samplesperpixel; - else - tv->count = fip->field_writecount; - - if (tv->count == 0) { - status = 0; - TIFFErrorExt(tif->tif_clientdata, module, - "%s: Null count for \"%s\" (type " - "%d, writecount %d, passcount %d)", - tif->tif_name, - fip->field_name, - fip->field_type, - fip->field_writecount, - fip->field_passcount); - goto end; - } - - tv->value = _TIFFCheckMalloc(tif, tv->count, tv_size, - "custom tag binary object"); - if (!tv->value) { - status = 0; - goto end; - } - - if (fip->field_tag == TIFFTAG_DOTRANGE - && strcmp(fip->field_name,"DotRange") == 0) { - /* TODO: This is an evil exception and should not have been - handled this way ... likely best if we move it into - the directory structure with an explicit field in - libtiff 4.1 and assign it a FIELD_ value */ - uint16 v[2]; - v[0] = (uint16)va_arg(ap, int); - v[1] = (uint16)va_arg(ap, int); - _TIFFmemcpy(tv->value, &v, 4); - } - - else if (fip->field_passcount - || fip->field_writecount == TIFF_VARIABLE - || fip->field_writecount == TIFF_VARIABLE2 - || fip->field_writecount == TIFF_SPP - || tv->count > 1) { - _TIFFmemcpy(tv->value, va_arg(ap, void *), - tv->count * tv_size); - } else { - char *val = (char *)tv->value; - assert( tv->count == 1 ); - - switch (fip->field_type) { - case TIFF_BYTE: - case TIFF_UNDEFINED: - { - uint8 v = (uint8)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_SBYTE: - { - int8 v = (int8)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_SHORT: - { - uint16 v = (uint16)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_SSHORT: - { - int16 v = (int16)va_arg(ap, int); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_LONG: - case TIFF_IFD: - { - uint32 v = va_arg(ap, uint32); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_SLONG: - { - int32 v = va_arg(ap, int32); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_LONG8: - case TIFF_IFD8: - { - uint64 v = va_arg(ap, uint64); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_SLONG8: - { - int64 v = va_arg(ap, int64); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - case TIFF_FLOAT: - { - float v = (float)va_arg(ap, double); - _TIFFmemcpy(val, &v, tv_size); - } - break; - case TIFF_DOUBLE: - { - double v = va_arg(ap, double); - _TIFFmemcpy(val, &v, tv_size); - } - break; - default: - _TIFFmemset(val, 0, tv_size); - status = 0; - break; - } + TIFFWarningExt(tif->tif_clientdata,module, + "SamplesPerPixel tag value is changing, " + "but SMaxSampleValue tag was read with a different value. Cancelling it"); + TIFFClrFieldBit(tif,FIELD_SMAXSAMPLEVALUE); + _TIFFfree(td->td_smaxsamplevalue); + td->td_smaxsamplevalue = NULL; } } - } - } - if (status) { - const TIFFField* fip=TIFFFieldWithTag(tif,tag); - if (fip) - TIFFSetFieldBit(tif, fip->field_bit); - tif->tif_flags |= TIFF_DIRTYDIRECT; - } + td->td_samplesperpixel = (uint16) v; + break; + case TIFFTAG_ROWSPERSTRIP: + v32 = (uint32) va_arg(ap, uint32); + if (v32 == 0) + goto badvalue32; + td->td_rowsperstrip = v32; + if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { + td->td_tilelength = v32; + td->td_tilewidth = td->td_imagewidth; + } + break; + case TIFFTAG_MINSAMPLEVALUE: + td->td_minsamplevalue = (uint16) va_arg(ap, uint16_vap); + break; + case TIFFTAG_MAXSAMPLEVALUE: + td->td_maxsamplevalue = (uint16) va_arg(ap, uint16_vap); + break; + case TIFFTAG_SMINSAMPLEVALUE: + if (tif->tif_flags & TIFF_PERSAMPLE) + _TIFFsetDoubleArray(&td->td_sminsamplevalue, va_arg(ap, double*), td->td_samplesperpixel); + else + setDoubleArrayOneValue(&td->td_sminsamplevalue, va_arg(ap, double), td->td_samplesperpixel); + break; + case TIFFTAG_SMAXSAMPLEVALUE: + if (tif->tif_flags & TIFF_PERSAMPLE) + _TIFFsetDoubleArray(&td->td_smaxsamplevalue, va_arg(ap, double*), td->td_samplesperpixel); + else + setDoubleArrayOneValue(&td->td_smaxsamplevalue, va_arg(ap, double), td->td_samplesperpixel); + break; + case TIFFTAG_XRESOLUTION: + dblval = va_arg(ap, double); + if( dblval < 0 ) + goto badvaluedouble; + td->td_xresolution = TIFFClampDoubleToFloat( dblval ); + break; + case TIFFTAG_YRESOLUTION: + dblval = va_arg(ap, double); + if( dblval < 0 ) + goto badvaluedouble; + td->td_yresolution = TIFFClampDoubleToFloat( dblval ); + break; + case TIFFTAG_PLANARCONFIG: + v = (uint16) va_arg(ap, uint16_vap); + if (v != PLANARCONFIG_CONTIG && v != PLANARCONFIG_SEPARATE) + goto badvalue; + td->td_planarconfig = (uint16) v; + break; + case TIFFTAG_XPOSITION: + td->td_xposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); + break; + case TIFFTAG_YPOSITION: + td->td_yposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); + break; + case TIFFTAG_RESOLUTIONUNIT: + v = (uint16) va_arg(ap, uint16_vap); + if (v < RESUNIT_NONE || RESUNIT_CENTIMETER < v) + goto badvalue; + td->td_resolutionunit = (uint16) v; + break; + case TIFFTAG_PAGENUMBER: + td->td_pagenumber[0] = (uint16) va_arg(ap, uint16_vap); + td->td_pagenumber[1] = (uint16) va_arg(ap, uint16_vap); + break; + case TIFFTAG_HALFTONEHINTS: + td->td_halftonehints[0] = (uint16) va_arg(ap, uint16_vap); + td->td_halftonehints[1] = (uint16) va_arg(ap, uint16_vap); + break; + case TIFFTAG_COLORMAP: + v32 = (uint32)(1L<td_bitspersample); + _TIFFsetShortArray(&td->td_colormap[0], va_arg(ap, uint16*), v32); + _TIFFsetShortArray(&td->td_colormap[1], va_arg(ap, uint16*), v32); + _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32); + break; + case TIFFTAG_EXTRASAMPLES: + if (!setExtraSamples(td, ap, &v)) + goto badvalue; + break; + case TIFFTAG_MATTEING: + td->td_extrasamples = (((uint16) va_arg(ap, uint16_vap)) != 0); + if (td->td_extrasamples) { + uint16 sv = EXTRASAMPLE_ASSOCALPHA; + _TIFFsetShortArray(&td->td_sampleinfo, &sv, 1); + } + break; + case TIFFTAG_TILEWIDTH: + v32 = (uint32) va_arg(ap, uint32); + if (v32 % 16) { + if (tif->tif_mode != O_RDONLY) + goto badvalue32; + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "Nonstandard tile width %d, convert file", v32); + } + td->td_tilewidth = v32; + tif->tif_flags |= TIFF_ISTILED; + break; + case TIFFTAG_TILELENGTH: + v32 = (uint32) va_arg(ap, uint32); + if (v32 % 16) { + if (tif->tif_mode != O_RDONLY) + goto badvalue32; + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "Nonstandard tile length %d, convert file", v32); + } + td->td_tilelength = v32; + tif->tif_flags |= TIFF_ISTILED; + break; + case TIFFTAG_TILEDEPTH: + v32 = (uint32) va_arg(ap, uint32); + if (v32 == 0) + goto badvalue32; + td->td_tiledepth = v32; + break; + case TIFFTAG_DATATYPE: + v = (uint16) va_arg(ap, uint16_vap); + switch (v) { + case DATATYPE_VOID: v = SAMPLEFORMAT_VOID; break; + case DATATYPE_INT: v = SAMPLEFORMAT_INT; break; + case DATATYPE_UINT: v = SAMPLEFORMAT_UINT; break; + case DATATYPE_IEEEFP: v = SAMPLEFORMAT_IEEEFP;break; + default: goto badvalue; + } + td->td_sampleformat = (uint16) v; + break; + case TIFFTAG_SAMPLEFORMAT: + v = (uint16) va_arg(ap, uint16_vap); + if (v < SAMPLEFORMAT_UINT || SAMPLEFORMAT_COMPLEXIEEEFP < v) + goto badvalue; + td->td_sampleformat = (uint16) v; + + /* Try to fix up the SWAB function for complex data. */ + if( td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT + && td->td_bitspersample == 32 + && tif->tif_postdecode == _TIFFSwab32BitData ) + tif->tif_postdecode = _TIFFSwab16BitData; + else if( (td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT + || td->td_sampleformat == SAMPLEFORMAT_COMPLEXIEEEFP) + && td->td_bitspersample == 64 + && tif->tif_postdecode == _TIFFSwab64BitData ) + tif->tif_postdecode = _TIFFSwab32BitData; + break; + case TIFFTAG_IMAGEDEPTH: + td->td_imagedepth = (uint32) va_arg(ap, uint32); + break; + case TIFFTAG_SUBIFD: + if ((tif->tif_flags & TIFF_INSUBIFD) == 0) { + td->td_nsubifd = (uint16) va_arg(ap, uint16_vap); + _TIFFsetLong8Array(&td->td_subifd, (uint64*) va_arg(ap, uint64*), + (uint32) td->td_nsubifd); + } else { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Sorry, cannot nest SubIFDs", + tif->tif_name); + status = 0; + } + break; + case TIFFTAG_YCBCRPOSITIONING: + td->td_ycbcrpositioning = (uint16) va_arg(ap, uint16_vap); + break; + case TIFFTAG_YCBCRSUBSAMPLING: + td->td_ycbcrsubsampling[0] = (uint16) va_arg(ap, uint16_vap); + td->td_ycbcrsubsampling[1] = (uint16) va_arg(ap, uint16_vap); + break; + case TIFFTAG_TRANSFERFUNCTION: + v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1; + for (i = 0; i < v; i++) + _TIFFsetShortArray(&td->td_transferfunction[i], + va_arg(ap, uint16*), 1U<td_bitspersample); + break; + case TIFFTAG_REFERENCEBLACKWHITE: + /* XXX should check for null range */ + _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6); + break; + case TIFFTAG_INKNAMES: + v = (uint16) va_arg(ap, uint16_vap); + s = va_arg(ap, char*); + v = checkInkNamesString(tif, v, s); + status = v > 0; + if( v > 0 ) { + _TIFFsetNString(&td->td_inknames, s, v); + td->td_inknameslen = v; + } + break; + case TIFFTAG_PERSAMPLE: + v = (uint16) va_arg(ap, uint16_vap); + if( v == PERSAMPLE_MULTI ) + tif->tif_flags |= TIFF_PERSAMPLE; + else + tif->tif_flags &= ~TIFF_PERSAMPLE; + break; + default: { + TIFFTagValue *tv; + int tv_size, iCustom; + + /* + * This can happen if multiple images are open with different + * codecs which have private tags. The global tag information + * table may then have tags that are valid for one file but not + * the other. If the client tries to set a tag that is not valid + * for the image's codec then we'll arrive here. This + * happens, for example, when tiffcp is used to convert between + * compression schemes and codec-specific tags are blindly copied. + */ + if(fip->field_bit != FIELD_CUSTOM) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Invalid %stag \"%s\" (not supported by codec)", + tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", + fip->field_name); + status = 0; + break; + } + + /* + * Find the existing entry for this custom value. + */ + tv = NULL; + for (iCustom = 0; iCustom < td->td_customValueCount; iCustom++) { + if (td->td_customValues[iCustom].info->field_tag == tag) { + tv = td->td_customValues + iCustom; + if (tv->value != NULL) { + _TIFFfree(tv->value); + tv->value = NULL; + } + break; + } + } + + /* + * Grow the custom list if the entry was not found. + */ + if(tv == NULL) { + TIFFTagValue *new_customValues; + + td->td_customValueCount++; + new_customValues = (TIFFTagValue *) + _TIFFrealloc(td->td_customValues, + sizeof(TIFFTagValue) * td->td_customValueCount); + if (!new_customValues) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Failed to allocate space for list of custom values", + tif->tif_name); + status = 0; + goto end; + } + + td->td_customValues = new_customValues; + + tv = td->td_customValues + (td->td_customValueCount - 1); + tv->info = fip; + tv->value = NULL; + tv->count = 0; + } + + /* + * Set custom value ... save a copy of the custom tag value. + */ + tv_size = _TIFFDataSize(fip->field_type); + if (tv_size == 0) { + status = 0; + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Bad field type %d for \"%s\"", + tif->tif_name, fip->field_type, + fip->field_name); + goto end; + } + + if (fip->field_type == TIFF_ASCII) + { + uint32 ma; + char* mb; + if (fip->field_passcount) + { + assert(fip->field_writecount==TIFF_VARIABLE2); + ma=(uint32)va_arg(ap,uint32); + mb=(char*)va_arg(ap,char*); + } + else + { + mb=(char*)va_arg(ap,char*); + ma=(uint32)(strlen(mb)+1); + } + tv->count=ma; + setByteArray(&tv->value,mb,ma,1); + } + else + { + if (fip->field_passcount) { + if (fip->field_writecount == TIFF_VARIABLE2) + tv->count = (uint32) va_arg(ap, uint32); + else + tv->count = (int) va_arg(ap, int); + } else if (fip->field_writecount == TIFF_VARIABLE + || fip->field_writecount == TIFF_VARIABLE2) + tv->count = 1; + else if (fip->field_writecount == TIFF_SPP) + tv->count = td->td_samplesperpixel; + else + tv->count = fip->field_writecount; + + if (tv->count == 0) { + status = 0; + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Null count for \"%s\" (type " + "%d, writecount %d, passcount %d)", + tif->tif_name, + fip->field_name, + fip->field_type, + fip->field_writecount, + fip->field_passcount); + goto end; + } + + tv->value = _TIFFCheckMalloc(tif, tv->count, tv_size, + "custom tag binary object"); + if (!tv->value) { + status = 0; + goto end; + } + + if (fip->field_tag == TIFFTAG_DOTRANGE + && strcmp(fip->field_name,"DotRange") == 0) { + /* TODO: This is an evil exception and should not have been + handled this way ... likely best if we move it into + the directory structure with an explicit field in + libtiff 4.1 and assign it a FIELD_ value */ + uint16 v2[2]; + v2[0] = (uint16)va_arg(ap, int); + v2[1] = (uint16)va_arg(ap, int); + _TIFFmemcpy(tv->value, &v2, 4); + } + + else if (fip->field_passcount + || fip->field_writecount == TIFF_VARIABLE + || fip->field_writecount == TIFF_VARIABLE2 + || fip->field_writecount == TIFF_SPP + || tv->count > 1) { + _TIFFmemcpy(tv->value, va_arg(ap, void *), + tv->count * tv_size); + } else { + char *val = (char *)tv->value; + assert( tv->count == 1 ); + + switch (fip->field_type) { + case TIFF_BYTE: + case TIFF_UNDEFINED: + { + uint8 v2 = (uint8)va_arg(ap, int); + _TIFFmemcpy(val, &v2, tv_size); + } + break; + case TIFF_SBYTE: + { + int8 v2 = (int8)va_arg(ap, int); + _TIFFmemcpy(val, &v2, tv_size); + } + break; + case TIFF_SHORT: + { + uint16 v2 = (uint16)va_arg(ap, int); + _TIFFmemcpy(val, &v2, tv_size); + } + break; + case TIFF_SSHORT: + { + int16 v2 = (int16)va_arg(ap, int); + _TIFFmemcpy(val, &v2, tv_size); + } + break; + case TIFF_LONG: + case TIFF_IFD: + { + uint32 v2 = va_arg(ap, uint32); + _TIFFmemcpy(val, &v2, tv_size); + } + break; + case TIFF_SLONG: + { + int32 v2 = va_arg(ap, int32); + _TIFFmemcpy(val, &v2, tv_size); + } + break; + case TIFF_LONG8: + case TIFF_IFD8: + { + uint64 v2 = va_arg(ap, uint64); + _TIFFmemcpy(val, &v2, tv_size); + } + break; + case TIFF_SLONG8: + { + int64 v2 = va_arg(ap, int64); + _TIFFmemcpy(val, &v2, tv_size); + } + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + { + float v2 = TIFFClampDoubleToFloat(va_arg(ap, double)); + _TIFFmemcpy(val, &v2, tv_size); + } + break; + case TIFF_DOUBLE: + { + double v2 = va_arg(ap, double); + _TIFFmemcpy(val, &v2, tv_size); + } + break; + default: + _TIFFmemset(val, 0, tv_size); + status = 0; + break; + } + } + } + } + } + if (status) { + const TIFFField* fip2=TIFFFieldWithTag(tif,tag); + if (fip2) + TIFFSetFieldBit(tif, fip2->field_bit); + tif->tif_flags |= TIFF_DIRTYDIRECT; + } end: - va_end(ap); - return (status); + va_end(ap); + return (status); badvalue: { - const TIFFField* fip=TIFFFieldWithTag(tif,tag); - TIFFErrorExt(tif->tif_clientdata, module, - "%s: Bad value %u for \"%s\" tag", - tif->tif_name, v, - fip ? fip->field_name : "Unknown"); - va_end(ap); + const TIFFField* fip2=TIFFFieldWithTag(tif,tag); + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Bad value %u for \"%s\" tag", + tif->tif_name, v, + fip2 ? fip2->field_name : "Unknown"); + va_end(ap); } - return (0); + return (0); badvalue32: { - const TIFFField* fip=TIFFFieldWithTag(tif,tag); + const TIFFField* fip2=TIFFFieldWithTag(tif,tag); + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Bad value %u for \"%s\" tag", + tif->tif_name, v32, + fip2 ? fip2->field_name : "Unknown"); + va_end(ap); + } + return (0); +badvaluedouble: + { + const TIFFField* fip2=TIFFFieldWithTag(tif,tag); TIFFErrorExt(tif->tif_clientdata, module, - "%s: Bad value %u for \"%s\" tag", - tif->tif_name, v32, - fip ? fip->field_name : "Unknown"); + "%s: Bad value %f for \"%s\" tag", + tif->tif_name, dblval, + fip2 ? fip2->field_name : "Unknown"); va_end(ap); } return (0); @@ -707,26 +759,26 @@ badvalue32: static int OkToChangeTag(TIFF* tif, uint32 tag) { - const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY); - if (!fip) { /* unknown tag */ - TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", "%s: Unknown %stag %u", - tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", tag); - return (0); - } - if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING) && - !fip->field_oktochange) { - /* - * Consult info table to see if tag can be changed - * after we've started writing. We only allow changes - * to those tags that don't/shouldn't affect the - * compression and/or format of the data. - */ - TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", - "%s: Cannot modify tag \"%s\" while writing", - tif->tif_name, fip->field_name); - return (0); - } - return (1); + const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY); + if (!fip) { /* unknown tag */ + TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", "%s: Unknown %stag %u", + tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", tag); + return (0); + } + if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING) && + !fip->field_oktochange) { + /* + * Consult info table to see if tag can be changed + * after we've started writing. We only allow changes + * to those tags that don't/shouldn't affect the + * compression and/or format of the data. + */ + TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", + "%s: Cannot modify tag \"%s\" while writing", + tif->tif_name, fip->field_name); + return (0); + } + return (1); } /* @@ -739,13 +791,13 @@ OkToChangeTag(TIFF* tif, uint32 tag) int TIFFSetField(TIFF* tif, uint32 tag, ...) { - va_list ap; - int status; + va_list ap; + int status; - va_start(ap, tag); - status = TIFFVSetField(tif, tag, ap); - va_end(ap); - return (status); + va_start(ap, tag); + status = TIFFVSetField(tif, tag, ap); + va_end(ap); + return (status); } /* @@ -768,7 +820,7 @@ TIFFUnsetField(TIFF* tif, uint32 tag) int i; for (i = 0; i < td->td_customValueCount; i++) { - + tv = td->td_customValues + i; if( tv->info->field_tag == tag ) break; @@ -783,7 +835,7 @@ TIFFUnsetField(TIFF* tif, uint32 tag) td->td_customValueCount--; } } - + tif->tif_flags |= TIFF_DIRTYDIRECT; return (1); @@ -798,330 +850,360 @@ TIFFUnsetField(TIFF* tif, uint32 tag) int TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) { - return OkToChangeTag(tif, tag) ? - (*tif->tif_tagmethods.vsetfield)(tif, tag, ap) : 0; + return OkToChangeTag(tif, tag) ? + (*tif->tif_tagmethods.vsetfield)(tif, tag, ap) : 0; } static int _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) { - TIFFDirectory* td = &tif->tif_dir; - int ret_val = 1; - uint32 standard_tag = tag; - const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY); - - /* - * We want to force the custom code to be used for custom - * fields even if the tag happens to match a well known - * one - important for reinterpreted handling of standard - * tag values in custom directories (ie. EXIF) - */ - if (fip->field_bit == FIELD_CUSTOM) { - standard_tag = 0; - } - - switch (standard_tag) { - case TIFFTAG_SUBFILETYPE: - *va_arg(ap, uint32*) = td->td_subfiletype; - break; - case TIFFTAG_IMAGEWIDTH: - *va_arg(ap, uint32*) = td->td_imagewidth; - break; - case TIFFTAG_IMAGELENGTH: - *va_arg(ap, uint32*) = td->td_imagelength; - break; - case TIFFTAG_BITSPERSAMPLE: - *va_arg(ap, uint16*) = td->td_bitspersample; - break; - case TIFFTAG_COMPRESSION: - *va_arg(ap, uint16*) = td->td_compression; - break; - case TIFFTAG_PHOTOMETRIC: - *va_arg(ap, uint16*) = td->td_photometric; - break; - case TIFFTAG_THRESHHOLDING: - *va_arg(ap, uint16*) = td->td_threshholding; - break; - case TIFFTAG_FILLORDER: - *va_arg(ap, uint16*) = td->td_fillorder; - break; - case TIFFTAG_ORIENTATION: - *va_arg(ap, uint16*) = td->td_orientation; - break; - case TIFFTAG_SAMPLESPERPIXEL: - *va_arg(ap, uint16*) = td->td_samplesperpixel; - break; - case TIFFTAG_ROWSPERSTRIP: - *va_arg(ap, uint32*) = td->td_rowsperstrip; - break; - case TIFFTAG_MINSAMPLEVALUE: - *va_arg(ap, uint16*) = td->td_minsamplevalue; - break; - case TIFFTAG_MAXSAMPLEVALUE: - *va_arg(ap, uint16*) = td->td_maxsamplevalue; - break; - case TIFFTAG_SMINSAMPLEVALUE: - if (tif->tif_flags & TIFF_PERSAMPLE) - *va_arg(ap, double**) = td->td_sminsamplevalue; - else - { - /* libtiff historially treats this as a single value. */ - uint16 i; - double v = td->td_sminsamplevalue[0]; - for (i=1; i < td->td_samplesperpixel; ++i) - if( td->td_sminsamplevalue[i] < v ) - v = td->td_sminsamplevalue[i]; - *va_arg(ap, double*) = v; - } - break; - case TIFFTAG_SMAXSAMPLEVALUE: - if (tif->tif_flags & TIFF_PERSAMPLE) - *va_arg(ap, double**) = td->td_smaxsamplevalue; - else - { - /* libtiff historially treats this as a single value. */ - uint16 i; - double v = td->td_smaxsamplevalue[0]; - for (i=1; i < td->td_samplesperpixel; ++i) - if( td->td_smaxsamplevalue[i] > v ) - v = td->td_smaxsamplevalue[i]; - *va_arg(ap, double*) = v; - } - break; - case TIFFTAG_XRESOLUTION: - *va_arg(ap, float*) = td->td_xresolution; - break; - case TIFFTAG_YRESOLUTION: - *va_arg(ap, float*) = td->td_yresolution; - break; - case TIFFTAG_PLANARCONFIG: - *va_arg(ap, uint16*) = td->td_planarconfig; - break; - case TIFFTAG_XPOSITION: - *va_arg(ap, float*) = td->td_xposition; - break; - case TIFFTAG_YPOSITION: - *va_arg(ap, float*) = td->td_yposition; - break; - case TIFFTAG_RESOLUTIONUNIT: - *va_arg(ap, uint16*) = td->td_resolutionunit; - break; - case TIFFTAG_PAGENUMBER: - *va_arg(ap, uint16*) = td->td_pagenumber[0]; - *va_arg(ap, uint16*) = td->td_pagenumber[1]; - break; - case TIFFTAG_HALFTONEHINTS: - *va_arg(ap, uint16*) = td->td_halftonehints[0]; - *va_arg(ap, uint16*) = td->td_halftonehints[1]; - break; - case TIFFTAG_COLORMAP: - *va_arg(ap, uint16**) = td->td_colormap[0]; - *va_arg(ap, uint16**) = td->td_colormap[1]; - *va_arg(ap, uint16**) = td->td_colormap[2]; - break; - case TIFFTAG_STRIPOFFSETS: - case TIFFTAG_TILEOFFSETS: - _TIFFFillStriles( tif ); - *va_arg(ap, uint64**) = td->td_stripoffset; - break; - case TIFFTAG_STRIPBYTECOUNTS: - case TIFFTAG_TILEBYTECOUNTS: - _TIFFFillStriles( tif ); - *va_arg(ap, uint64**) = td->td_stripbytecount; - break; - case TIFFTAG_MATTEING: - *va_arg(ap, uint16*) = - (td->td_extrasamples == 1 && - td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA); - break; - case TIFFTAG_EXTRASAMPLES: - *va_arg(ap, uint16*) = td->td_extrasamples; - *va_arg(ap, uint16**) = td->td_sampleinfo; - break; - case TIFFTAG_TILEWIDTH: - *va_arg(ap, uint32*) = td->td_tilewidth; - break; - case TIFFTAG_TILELENGTH: - *va_arg(ap, uint32*) = td->td_tilelength; - break; - case TIFFTAG_TILEDEPTH: - *va_arg(ap, uint32*) = td->td_tiledepth; - break; - case TIFFTAG_DATATYPE: - switch (td->td_sampleformat) { - case SAMPLEFORMAT_UINT: - *va_arg(ap, uint16*) = DATATYPE_UINT; - break; - case SAMPLEFORMAT_INT: - *va_arg(ap, uint16*) = DATATYPE_INT; - break; - case SAMPLEFORMAT_IEEEFP: - *va_arg(ap, uint16*) = DATATYPE_IEEEFP; - break; - case SAMPLEFORMAT_VOID: - *va_arg(ap, uint16*) = DATATYPE_VOID; - break; - } - break; - case TIFFTAG_SAMPLEFORMAT: - *va_arg(ap, uint16*) = td->td_sampleformat; - break; - case TIFFTAG_IMAGEDEPTH: - *va_arg(ap, uint32*) = td->td_imagedepth; - break; - case TIFFTAG_SUBIFD: - *va_arg(ap, uint16*) = td->td_nsubifd; - *va_arg(ap, uint64**) = td->td_subifd; - break; - case TIFFTAG_YCBCRPOSITIONING: - *va_arg(ap, uint16*) = td->td_ycbcrpositioning; - break; - case TIFFTAG_YCBCRSUBSAMPLING: - *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[0]; - *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[1]; - break; - case TIFFTAG_TRANSFERFUNCTION: - *va_arg(ap, uint16**) = td->td_transferfunction[0]; - if (td->td_samplesperpixel - td->td_extrasamples > 1) { - *va_arg(ap, uint16**) = td->td_transferfunction[1]; - *va_arg(ap, uint16**) = td->td_transferfunction[2]; - } - break; - case TIFFTAG_REFERENCEBLACKWHITE: - *va_arg(ap, float**) = td->td_refblackwhite; - break; - case TIFFTAG_INKNAMES: - *va_arg(ap, char**) = td->td_inknames; - break; - default: - { - int i; - - /* - * This can happen if multiple images are open - * with different codecs which have private - * tags. The global tag information table may - * then have tags that are valid for one file - * but not the other. If the client tries to - * get a tag that is not valid for the image's - * codec then we'll arrive here. - */ - if( fip == NULL || fip->field_bit != FIELD_CUSTOM ) + TIFFDirectory* td = &tif->tif_dir; + int ret_val = 1; + uint32 standard_tag = tag; + const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY); + if( fip == NULL ) /* cannot happen since TIFFGetField() already checks it */ + return 0; + + if( tag == TIFFTAG_NUMBEROFINKS ) + { + int i; + for (i = 0; i < td->td_customValueCount; i++) { + uint16 val; + TIFFTagValue *tv = td->td_customValues + i; + if (tv->info->field_tag != tag) + continue; + if( tv->value == NULL ) + return 0; + val = *(uint16 *)tv->value; + /* Truncate to SamplesPerPixel, since the */ + /* setting code for INKNAMES assume that there are SamplesPerPixel */ + /* inknames. */ + /* Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2599 */ + if( val > td->td_samplesperpixel ) { - TIFFErrorExt(tif->tif_clientdata, "_TIFFVGetField", - "%s: Invalid %stag \"%s\" " - "(not supported by codec)", - tif->tif_name, - isPseudoTag(tag) ? "pseudo-" : "", - fip ? fip->field_name : "Unknown"); - ret_val = 0; - break; - } - - /* - * Do we have a custom value? - */ - ret_val = 0; - for (i = 0; i < td->td_customValueCount; i++) { - TIFFTagValue *tv = td->td_customValues + i; - - if (tv->info->field_tag != tag) - continue; - - if (fip->field_passcount) { - if (fip->field_readcount == TIFF_VARIABLE2) - *va_arg(ap, uint32*) = (uint32)tv->count; - else /* Assume TIFF_VARIABLE */ - *va_arg(ap, uint16*) = (uint16)tv->count; - *va_arg(ap, void **) = tv->value; - ret_val = 1; - } else if (fip->field_tag == TIFFTAG_DOTRANGE - && strcmp(fip->field_name,"DotRange") == 0) { - /* TODO: This is an evil exception and should not have been - handled this way ... likely best if we move it into - the directory structure with an explicit field in - libtiff 4.1 and assign it a FIELD_ value */ - *va_arg(ap, uint16*) = ((uint16 *)tv->value)[0]; - *va_arg(ap, uint16*) = ((uint16 *)tv->value)[1]; - ret_val = 1; - } else { - if (fip->field_type == TIFF_ASCII - || fip->field_readcount == TIFF_VARIABLE - || fip->field_readcount == TIFF_VARIABLE2 - || fip->field_readcount == TIFF_SPP - || tv->count > 1) { - *va_arg(ap, void **) = tv->value; - ret_val = 1; - } else { - char *val = (char *)tv->value; - assert( tv->count == 1 ); - switch (fip->field_type) { - case TIFF_BYTE: - case TIFF_UNDEFINED: - *va_arg(ap, uint8*) = - *(uint8 *)val; - ret_val = 1; - break; - case TIFF_SBYTE: - *va_arg(ap, int8*) = - *(int8 *)val; - ret_val = 1; - break; - case TIFF_SHORT: - *va_arg(ap, uint16*) = - *(uint16 *)val; - ret_val = 1; - break; - case TIFF_SSHORT: - *va_arg(ap, int16*) = - *(int16 *)val; - ret_val = 1; - break; - case TIFF_LONG: - case TIFF_IFD: - *va_arg(ap, uint32*) = - *(uint32 *)val; - ret_val = 1; - break; - case TIFF_SLONG: - *va_arg(ap, int32*) = - *(int32 *)val; - ret_val = 1; - break; - case TIFF_LONG8: - case TIFF_IFD8: - *va_arg(ap, uint64*) = - *(uint64 *)val; - ret_val = 1; - break; - case TIFF_SLONG8: - *va_arg(ap, int64*) = - *(int64 *)val; - ret_val = 1; - break; - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - case TIFF_FLOAT: - *va_arg(ap, float*) = - *(float *)val; - ret_val = 1; - break; - case TIFF_DOUBLE: - *va_arg(ap, double*) = - *(double *)val; - ret_val = 1; - break; - default: - ret_val = 0; - break; - } - } - } - break; + TIFFWarningExt(tif->tif_clientdata,"_TIFFVGetField", + "Truncating NumberOfInks from %u to %u", + val, td->td_samplesperpixel); + val = td->td_samplesperpixel; } + *va_arg(ap, uint16*) = val; + return 1; } - } - return(ret_val); + return 0; + } + + /* + * We want to force the custom code to be used for custom + * fields even if the tag happens to match a well known + * one - important for reinterpreted handling of standard + * tag values in custom directories (i.e. EXIF) + */ + if (fip->field_bit == FIELD_CUSTOM) { + standard_tag = 0; + } + + switch (standard_tag) { + case TIFFTAG_SUBFILETYPE: + *va_arg(ap, uint32*) = td->td_subfiletype; + break; + case TIFFTAG_IMAGEWIDTH: + *va_arg(ap, uint32*) = td->td_imagewidth; + break; + case TIFFTAG_IMAGELENGTH: + *va_arg(ap, uint32*) = td->td_imagelength; + break; + case TIFFTAG_BITSPERSAMPLE: + *va_arg(ap, uint16*) = td->td_bitspersample; + break; + case TIFFTAG_COMPRESSION: + *va_arg(ap, uint16*) = td->td_compression; + break; + case TIFFTAG_PHOTOMETRIC: + *va_arg(ap, uint16*) = td->td_photometric; + break; + case TIFFTAG_THRESHHOLDING: + *va_arg(ap, uint16*) = td->td_threshholding; + break; + case TIFFTAG_FILLORDER: + *va_arg(ap, uint16*) = td->td_fillorder; + break; + case TIFFTAG_ORIENTATION: + *va_arg(ap, uint16*) = td->td_orientation; + break; + case TIFFTAG_SAMPLESPERPIXEL: + *va_arg(ap, uint16*) = td->td_samplesperpixel; + break; + case TIFFTAG_ROWSPERSTRIP: + *va_arg(ap, uint32*) = td->td_rowsperstrip; + break; + case TIFFTAG_MINSAMPLEVALUE: + *va_arg(ap, uint16*) = td->td_minsamplevalue; + break; + case TIFFTAG_MAXSAMPLEVALUE: + *va_arg(ap, uint16*) = td->td_maxsamplevalue; + break; + case TIFFTAG_SMINSAMPLEVALUE: + if (tif->tif_flags & TIFF_PERSAMPLE) + *va_arg(ap, double**) = td->td_sminsamplevalue; + else + { + /* libtiff historically treats this as a single value. */ + uint16 i; + double v = td->td_sminsamplevalue[0]; + for (i=1; i < td->td_samplesperpixel; ++i) + if( td->td_sminsamplevalue[i] < v ) + v = td->td_sminsamplevalue[i]; + *va_arg(ap, double*) = v; + } + break; + case TIFFTAG_SMAXSAMPLEVALUE: + if (tif->tif_flags & TIFF_PERSAMPLE) + *va_arg(ap, double**) = td->td_smaxsamplevalue; + else + { + /* libtiff historically treats this as a single value. */ + uint16 i; + double v = td->td_smaxsamplevalue[0]; + for (i=1; i < td->td_samplesperpixel; ++i) + if( td->td_smaxsamplevalue[i] > v ) + v = td->td_smaxsamplevalue[i]; + *va_arg(ap, double*) = v; + } + break; + case TIFFTAG_XRESOLUTION: + *va_arg(ap, float*) = td->td_xresolution; + break; + case TIFFTAG_YRESOLUTION: + *va_arg(ap, float*) = td->td_yresolution; + break; + case TIFFTAG_PLANARCONFIG: + *va_arg(ap, uint16*) = td->td_planarconfig; + break; + case TIFFTAG_XPOSITION: + *va_arg(ap, float*) = td->td_xposition; + break; + case TIFFTAG_YPOSITION: + *va_arg(ap, float*) = td->td_yposition; + break; + case TIFFTAG_RESOLUTIONUNIT: + *va_arg(ap, uint16*) = td->td_resolutionunit; + break; + case TIFFTAG_PAGENUMBER: + *va_arg(ap, uint16*) = td->td_pagenumber[0]; + *va_arg(ap, uint16*) = td->td_pagenumber[1]; + break; + case TIFFTAG_HALFTONEHINTS: + *va_arg(ap, uint16*) = td->td_halftonehints[0]; + *va_arg(ap, uint16*) = td->td_halftonehints[1]; + break; + case TIFFTAG_COLORMAP: + *va_arg(ap, uint16**) = td->td_colormap[0]; + *va_arg(ap, uint16**) = td->td_colormap[1]; + *va_arg(ap, uint16**) = td->td_colormap[2]; + break; + case TIFFTAG_STRIPOFFSETS: + case TIFFTAG_TILEOFFSETS: + _TIFFFillStriles( tif ); + *va_arg(ap, uint64**) = td->td_stripoffset; + break; + case TIFFTAG_STRIPBYTECOUNTS: + case TIFFTAG_TILEBYTECOUNTS: + _TIFFFillStriles( tif ); + *va_arg(ap, uint64**) = td->td_stripbytecount; + break; + case TIFFTAG_MATTEING: + *va_arg(ap, uint16*) = + (td->td_extrasamples == 1 && + td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA); + break; + case TIFFTAG_EXTRASAMPLES: + *va_arg(ap, uint16*) = td->td_extrasamples; + *va_arg(ap, uint16**) = td->td_sampleinfo; + break; + case TIFFTAG_TILEWIDTH: + *va_arg(ap, uint32*) = td->td_tilewidth; + break; + case TIFFTAG_TILELENGTH: + *va_arg(ap, uint32*) = td->td_tilelength; + break; + case TIFFTAG_TILEDEPTH: + *va_arg(ap, uint32*) = td->td_tiledepth; + break; + case TIFFTAG_DATATYPE: + switch (td->td_sampleformat) { + case SAMPLEFORMAT_UINT: + *va_arg(ap, uint16*) = DATATYPE_UINT; + break; + case SAMPLEFORMAT_INT: + *va_arg(ap, uint16*) = DATATYPE_INT; + break; + case SAMPLEFORMAT_IEEEFP: + *va_arg(ap, uint16*) = DATATYPE_IEEEFP; + break; + case SAMPLEFORMAT_VOID: + *va_arg(ap, uint16*) = DATATYPE_VOID; + break; + } + break; + case TIFFTAG_SAMPLEFORMAT: + *va_arg(ap, uint16*) = td->td_sampleformat; + break; + case TIFFTAG_IMAGEDEPTH: + *va_arg(ap, uint32*) = td->td_imagedepth; + break; + case TIFFTAG_SUBIFD: + *va_arg(ap, uint16*) = td->td_nsubifd; + *va_arg(ap, uint64**) = td->td_subifd; + break; + case TIFFTAG_YCBCRPOSITIONING: + *va_arg(ap, uint16*) = td->td_ycbcrpositioning; + break; + case TIFFTAG_YCBCRSUBSAMPLING: + *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[0]; + *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[1]; + break; + case TIFFTAG_TRANSFERFUNCTION: + *va_arg(ap, uint16**) = td->td_transferfunction[0]; + if (td->td_samplesperpixel - td->td_extrasamples > 1) { + *va_arg(ap, uint16**) = td->td_transferfunction[1]; + *va_arg(ap, uint16**) = td->td_transferfunction[2]; + } + break; + case TIFFTAG_REFERENCEBLACKWHITE: + *va_arg(ap, float**) = td->td_refblackwhite; + break; + case TIFFTAG_INKNAMES: + *va_arg(ap, char**) = td->td_inknames; + break; + default: + { + int i; + + /* + * This can happen if multiple images are open + * with different codecs which have private + * tags. The global tag information table may + * then have tags that are valid for one file + * but not the other. If the client tries to + * get a tag that is not valid for the image's + * codec then we'll arrive here. + */ + if( fip->field_bit != FIELD_CUSTOM ) + { + TIFFErrorExt(tif->tif_clientdata, "_TIFFVGetField", + "%s: Invalid %stag \"%s\" " + "(not supported by codec)", + tif->tif_name, + isPseudoTag(tag) ? "pseudo-" : "", + fip->field_name); + ret_val = 0; + break; + } + + /* + * Do we have a custom value? + */ + ret_val = 0; + for (i = 0; i < td->td_customValueCount; i++) { + TIFFTagValue *tv = td->td_customValues + i; + + if (tv->info->field_tag != tag) + continue; + + if (fip->field_passcount) { + if (fip->field_readcount == TIFF_VARIABLE2) + *va_arg(ap, uint32*) = (uint32)tv->count; + else /* Assume TIFF_VARIABLE */ + *va_arg(ap, uint16*) = (uint16)tv->count; + *va_arg(ap, void **) = tv->value; + ret_val = 1; + } else if (fip->field_tag == TIFFTAG_DOTRANGE + && strcmp(fip->field_name,"DotRange") == 0) { + /* TODO: This is an evil exception and should not have been + handled this way ... likely best if we move it into + the directory structure with an explicit field in + libtiff 4.1 and assign it a FIELD_ value */ + *va_arg(ap, uint16*) = ((uint16 *)tv->value)[0]; + *va_arg(ap, uint16*) = ((uint16 *)tv->value)[1]; + ret_val = 1; + } else { + if (fip->field_type == TIFF_ASCII + || fip->field_readcount == TIFF_VARIABLE + || fip->field_readcount == TIFF_VARIABLE2 + || fip->field_readcount == TIFF_SPP + || tv->count > 1) { + *va_arg(ap, void **) = tv->value; + ret_val = 1; + } else { + char *val = (char *)tv->value; + assert( tv->count == 1 ); + switch (fip->field_type) { + case TIFF_BYTE: + case TIFF_UNDEFINED: + *va_arg(ap, uint8*) = + *(uint8 *)val; + ret_val = 1; + break; + case TIFF_SBYTE: + *va_arg(ap, int8*) = + *(int8 *)val; + ret_val = 1; + break; + case TIFF_SHORT: + *va_arg(ap, uint16*) = + *(uint16 *)val; + ret_val = 1; + break; + case TIFF_SSHORT: + *va_arg(ap, int16*) = + *(int16 *)val; + ret_val = 1; + break; + case TIFF_LONG: + case TIFF_IFD: + *va_arg(ap, uint32*) = + *(uint32 *)val; + ret_val = 1; + break; + case TIFF_SLONG: + *va_arg(ap, int32*) = + *(int32 *)val; + ret_val = 1; + break; + case TIFF_LONG8: + case TIFF_IFD8: + *va_arg(ap, uint64*) = + *(uint64 *)val; + ret_val = 1; + break; + case TIFF_SLONG8: + *va_arg(ap, int64*) = + *(int64 *)val; + ret_val = 1; + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + *va_arg(ap, float*) = + *(float *)val; + ret_val = 1; + break; + case TIFF_DOUBLE: + *va_arg(ap, double*) = + *(double *)val; + ret_val = 1; + break; + default: + ret_val = 0; + break; + } + } + } + break; + } + } + } + return(ret_val); } /* @@ -1131,13 +1213,13 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) int TIFFGetField(TIFF* tif, uint32 tag, ...) { - int status; - va_list ap; + int status; + va_list ap; - va_start(ap, tag); - status = TIFFVGetField(tif, tag, ap); - va_end(ap); - return (status); + va_start(ap, tag); + status = TIFFVGetField(tif, tag, ap); + va_end(ap); + return (status); } /* @@ -1149,15 +1231,15 @@ TIFFGetField(TIFF* tif, uint32 tag, ...) int TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) { - const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY); - return (fip && (isPseudoTag(tag) || TIFFFieldSet(tif, fip->field_bit)) ? - (*tif->tif_tagmethods.vgetfield)(tif, tag, ap) : 0); + const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY); + return (fip && (isPseudoTag(tag) || TIFFFieldSet(tif, fip->field_bit)) ? + (*tif->tif_tagmethods.vgetfield)(tif, tag, ap) : 0); } #define CleanupField(member) { \ if (td->member) { \ - _TIFFfree(td->member); \ - td->member = 0; \ + _TIFFfree(td->member); \ + td->member = 0; \ } \ } @@ -1167,40 +1249,40 @@ TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) void TIFFFreeDirectory(TIFF* tif) { - TIFFDirectory *td = &tif->tif_dir; - int i; + TIFFDirectory *td = &tif->tif_dir; + int i; - _TIFFmemset(td->td_fieldsset, 0, FIELD_SETLONGS); - CleanupField(td_sminsamplevalue); - CleanupField(td_smaxsamplevalue); - CleanupField(td_colormap[0]); - CleanupField(td_colormap[1]); - CleanupField(td_colormap[2]); - CleanupField(td_sampleinfo); - CleanupField(td_subifd); - CleanupField(td_inknames); - CleanupField(td_refblackwhite); - CleanupField(td_transferfunction[0]); - CleanupField(td_transferfunction[1]); - CleanupField(td_transferfunction[2]); - CleanupField(td_stripoffset); - CleanupField(td_stripbytecount); - TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING); - TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING); + _TIFFmemset(td->td_fieldsset, 0, FIELD_SETLONGS); + CleanupField(td_sminsamplevalue); + CleanupField(td_smaxsamplevalue); + CleanupField(td_colormap[0]); + CleanupField(td_colormap[1]); + CleanupField(td_colormap[2]); + CleanupField(td_sampleinfo); + CleanupField(td_subifd); + CleanupField(td_inknames); + CleanupField(td_refblackwhite); + CleanupField(td_transferfunction[0]); + CleanupField(td_transferfunction[1]); + CleanupField(td_transferfunction[2]); + CleanupField(td_stripoffset); + CleanupField(td_stripbytecount); + TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING); + TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING); - /* Cleanup custom tag values */ - for( i = 0; i < td->td_customValueCount; i++ ) { - if (td->td_customValues[i].value) - _TIFFfree(td->td_customValues[i].value); - } + /* Cleanup custom tag values */ + for( i = 0; i < td->td_customValueCount; i++ ) { + if (td->td_customValues[i].value) + _TIFFfree(td->td_customValues[i].value); + } - td->td_customValueCount = 0; - CleanupField(td_customValues); + td->td_customValueCount = 0; + CleanupField(td_customValues); #if defined(DEFER_STRILE_LOAD) _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry)); _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry)); -#endif +#endif } #undef CleanupField @@ -1212,9 +1294,9 @@ static TIFFExtendProc _TIFFextender = (TIFFExtendProc) NULL; TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc extender) { - TIFFExtendProc prev = _TIFFextender; - _TIFFextender = extender; - return (prev); + TIFFExtendProc prev = _TIFFextender; + _TIFFextender = extender; + return (prev); } /* @@ -1227,43 +1309,43 @@ TIFFSetTagExtender(TIFFExtendProc extender) int TIFFCreateDirectory(TIFF* tif) { - TIFFDefaultDirectory(tif); - tif->tif_diroff = 0; - tif->tif_nextdiroff = 0; - tif->tif_curoff = 0; - tif->tif_row = (uint32) -1; - tif->tif_curstrip = (uint32) -1; + TIFFDefaultDirectory(tif); + tif->tif_diroff = 0; + tif->tif_nextdiroff = 0; + tif->tif_curoff = 0; + tif->tif_row = (uint32) -1; + tif->tif_curstrip = (uint32) -1; - return 0; + return 0; } int TIFFCreateCustomDirectory(TIFF* tif, const TIFFFieldArray* infoarray) { - TIFFDefaultDirectory(tif); + TIFFDefaultDirectory(tif); - /* - * Reset the field definitions to match the application provided list. - * Hopefully TIFFDefaultDirectory() won't have done anything irreversable - * based on it's assumption this is an image directory. - */ - _TIFFSetupFields(tif, infoarray); + /* + * Reset the field definitions to match the application provided list. + * Hopefully TIFFDefaultDirectory() won't have done anything irreversable + * based on it's assumption this is an image directory. + */ + _TIFFSetupFields(tif, infoarray); - tif->tif_diroff = 0; - tif->tif_nextdiroff = 0; - tif->tif_curoff = 0; - tif->tif_row = (uint32) -1; - tif->tif_curstrip = (uint32) -1; + tif->tif_diroff = 0; + tif->tif_nextdiroff = 0; + tif->tif_curoff = 0; + tif->tif_row = (uint32) -1; + tif->tif_curstrip = (uint32) -1; - return 0; + return 0; } int TIFFCreateEXIFDirectory(TIFF* tif) { - const TIFFFieldArray* exifFieldArray; - exifFieldArray = _TIFFGetExifFields(); - return TIFFCreateCustomDirectory(tif, exifFieldArray); + const TIFFFieldArray* exifFieldArray; + exifFieldArray = _TIFFGetExifFields(); + return TIFFCreateCustomDirectory(tif, exifFieldArray); } /* @@ -1272,196 +1354,210 @@ TIFFCreateEXIFDirectory(TIFF* tif) int TIFFDefaultDirectory(TIFF* tif) { - register TIFFDirectory* td = &tif->tif_dir; - const TIFFFieldArray* tiffFieldArray; + register TIFFDirectory* td = &tif->tif_dir; + const TIFFFieldArray* tiffFieldArray; - tiffFieldArray = _TIFFGetFields(); - _TIFFSetupFields(tif, tiffFieldArray); + tiffFieldArray = _TIFFGetFields(); + _TIFFSetupFields(tif, tiffFieldArray); - _TIFFmemset(td, 0, sizeof (*td)); - td->td_fillorder = FILLORDER_MSB2LSB; - td->td_bitspersample = 1; - td->td_threshholding = THRESHHOLD_BILEVEL; - td->td_orientation = ORIENTATION_TOPLEFT; - td->td_samplesperpixel = 1; - td->td_rowsperstrip = (uint32) -1; - td->td_tilewidth = 0; - td->td_tilelength = 0; - td->td_tiledepth = 1; - td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */ - td->td_resolutionunit = RESUNIT_INCH; - td->td_sampleformat = SAMPLEFORMAT_UINT; - td->td_imagedepth = 1; - td->td_ycbcrsubsampling[0] = 2; - td->td_ycbcrsubsampling[1] = 2; - td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED; - tif->tif_postdecode = _TIFFNoPostDecode; - tif->tif_foundfield = NULL; - tif->tif_tagmethods.vsetfield = _TIFFVSetField; - tif->tif_tagmethods.vgetfield = _TIFFVGetField; - tif->tif_tagmethods.printdir = NULL; - /* - * Give client code a chance to install their own - * tag extensions & methods, prior to compression overloads. - */ - if (_TIFFextender) - (*_TIFFextender)(tif); - (void) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); - /* - * NB: The directory is marked dirty as a result of setting - * up the default compression scheme. However, this really - * isn't correct -- we want TIFF_DIRTYDIRECT to be set only - * if the user does something. We could just do the setup - * by hand, but it seems better to use the normal mechanism - * (i.e. TIFFSetField). - */ - tif->tif_flags &= ~TIFF_DIRTYDIRECT; + _TIFFmemset(td, 0, sizeof (*td)); + td->td_fillorder = FILLORDER_MSB2LSB; + td->td_bitspersample = 1; + td->td_threshholding = THRESHHOLD_BILEVEL; + td->td_orientation = ORIENTATION_TOPLEFT; + td->td_samplesperpixel = 1; + td->td_rowsperstrip = (uint32) -1; + td->td_tilewidth = 0; + td->td_tilelength = 0; + td->td_tiledepth = 1; + td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */ + td->td_resolutionunit = RESUNIT_INCH; + td->td_sampleformat = SAMPLEFORMAT_UINT; + td->td_imagedepth = 1; + td->td_ycbcrsubsampling[0] = 2; + td->td_ycbcrsubsampling[1] = 2; + td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED; + tif->tif_postdecode = _TIFFNoPostDecode; + tif->tif_foundfield = NULL; + tif->tif_tagmethods.vsetfield = _TIFFVSetField; + tif->tif_tagmethods.vgetfield = _TIFFVGetField; + tif->tif_tagmethods.printdir = NULL; + /* + * Give client code a chance to install their own + * tag extensions & methods, prior to compression overloads, + * but do some prior cleanup first. (http://trac.osgeo.org/gdal/ticket/5054) + */ + if (tif->tif_nfieldscompat > 0) { + uint32 i; - /* - * As per http://bugzilla.remotesensing.org/show_bug.cgi?id=19 - * we clear the ISTILED flag when setting up a new directory. - * Should we also be clearing stuff like INSUBIFD? - */ - tif->tif_flags &= ~TIFF_ISTILED; + for (i = 0; i < tif->tif_nfieldscompat; i++) { + if (tif->tif_fieldscompat[i].allocated_size) + _TIFFfree(tif->tif_fieldscompat[i].fields); + } + _TIFFfree(tif->tif_fieldscompat); + tif->tif_nfieldscompat = 0; + tif->tif_fieldscompat = NULL; + } + if (_TIFFextender) + (*_TIFFextender)(tif); + (void) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + /* + * NB: The directory is marked dirty as a result of setting + * up the default compression scheme. However, this really + * isn't correct -- we want TIFF_DIRTYDIRECT to be set only + * if the user does something. We could just do the setup + * by hand, but it seems better to use the normal mechanism + * (i.e. TIFFSetField). + */ + tif->tif_flags &= ~TIFF_DIRTYDIRECT; - return (1); + /* + * As per http://bugzilla.remotesensing.org/show_bug.cgi?id=19 + * we clear the ISTILED flag when setting up a new directory. + * Should we also be clearing stuff like INSUBIFD? + */ + tif->tif_flags &= ~TIFF_ISTILED; + + return (1); } static int TIFFAdvanceDirectory(TIFF* tif, uint64* nextdir, uint64* off) { - static const char module[] = "TIFFAdvanceDirectory"; - if (isMapped(tif)) - { - uint64 poff=*nextdir; - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - tmsize_t poffa,poffb,poffc,poffd; - uint16 dircount; - uint32 nextdir32; - poffa=(tmsize_t)poff; - poffb=poffa+sizeof(uint16); - if (((uint64)poffa!=poff)||(poffbtif->tif_size)) - { - TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory count"); - return(0); - } - _TIFFmemcpy(&dircount,tif->tif_base+poffa,sizeof(uint16)); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabShort(&dircount); - poffc=poffb+dircount*12; - poffd=poffc+sizeof(uint32); - if ((poffctif->tif_size)) - { - TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory link"); - return(0); - } - if (off!=NULL) - *off=(uint64)poffc; - _TIFFmemcpy(&nextdir32,tif->tif_base+poffc,sizeof(uint32)); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&nextdir32); - *nextdir=nextdir32; - } - else - { - tmsize_t poffa,poffb,poffc,poffd; - uint64 dircount64; - uint16 dircount16; - poffa=(tmsize_t)poff; - poffb=poffa+sizeof(uint64); - if (((uint64)poffa!=poff)||(poffbtif->tif_size)) - { - TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory count"); - return(0); - } - _TIFFmemcpy(&dircount64,tif->tif_base+poffa,sizeof(uint64)); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8(&dircount64); - if (dircount64>0xFFFF) - { - TIFFErrorExt(tif->tif_clientdata,module,"Sanity check on directory count failed"); - return(0); - } - dircount16=(uint16)dircount64; - poffc=poffb+dircount16*20; - poffd=poffc+sizeof(uint64); - if ((poffctif->tif_size)) - { - TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory link"); - return(0); - } - if (off!=NULL) - *off=(uint64)poffc; - _TIFFmemcpy(nextdir,tif->tif_base+poffc,sizeof(uint64)); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8(nextdir); - } - return(1); - } - else - { - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - uint16 dircount; - uint32 nextdir32; - if (!SeekOK(tif, *nextdir) || - !ReadOK(tif, &dircount, sizeof (uint16))) { - TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count", - tif->tif_name); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabShort(&dircount); - if (off != NULL) - *off = TIFFSeekFile(tif, - dircount*12, SEEK_CUR); - else - (void) TIFFSeekFile(tif, - dircount*12, SEEK_CUR); - if (!ReadOK(tif, &nextdir32, sizeof (uint32))) { - TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link", - tif->tif_name); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong(&nextdir32); - *nextdir=nextdir32; - } - else - { - uint64 dircount64; - uint16 dircount16; - if (!SeekOK(tif, *nextdir) || - !ReadOK(tif, &dircount64, sizeof (uint64))) { - TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count", - tif->tif_name); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(&dircount64); - if (dircount64>0xFFFF) - { - TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count"); - return(0); - } - dircount16 = (uint16)dircount64; - if (off != NULL) - *off = TIFFSeekFile(tif, - dircount16*20, SEEK_CUR); - else - (void) TIFFSeekFile(tif, - dircount16*20, SEEK_CUR); - if (!ReadOK(tif, nextdir, sizeof (uint64))) { - TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link", - tif->tif_name); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(nextdir); - } - return (1); - } + static const char module[] = "TIFFAdvanceDirectory"; + if (isMapped(tif)) + { + uint64 poff=*nextdir; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + tmsize_t poffa,poffb,poffc,poffd; + uint16 dircount; + uint32 nextdir32; + poffa=(tmsize_t)poff; + poffb=poffa+sizeof(uint16); + if (((uint64)poffa!=poff)||(poffbtif->tif_size)) + { + TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory count"); + *nextdir=0; + return(0); + } + _TIFFmemcpy(&dircount,tif->tif_base+poffa,sizeof(uint16)); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabShort(&dircount); + poffc=poffb+dircount*12; + poffd=poffc+sizeof(uint32); + if ((poffctif->tif_size)) + { + TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory link"); + return(0); + } + if (off!=NULL) + *off=(uint64)poffc; + _TIFFmemcpy(&nextdir32,tif->tif_base+poffc,sizeof(uint32)); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&nextdir32); + *nextdir=nextdir32; + } + else + { + tmsize_t poffa,poffb,poffc,poffd; + uint64 dircount64; + uint16 dircount16; + poffa=(tmsize_t)poff; + poffb=poffa+sizeof(uint64); + if (((uint64)poffa!=poff)||(poffbtif->tif_size)) + { + TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory count"); + return(0); + } + _TIFFmemcpy(&dircount64,tif->tif_base+poffa,sizeof(uint64)); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8(&dircount64); + if (dircount64>0xFFFF) + { + TIFFErrorExt(tif->tif_clientdata,module,"Sanity check on directory count failed"); + return(0); + } + dircount16=(uint16)dircount64; + poffc=poffb+dircount16*20; + poffd=poffc+sizeof(uint64); + if ((poffctif->tif_size)) + { + TIFFErrorExt(tif->tif_clientdata,module,"Error fetching directory link"); + return(0); + } + if (off!=NULL) + *off=(uint64)poffc; + _TIFFmemcpy(nextdir,tif->tif_base+poffc,sizeof(uint64)); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8(nextdir); + } + return(1); + } + else + { + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + uint16 dircount; + uint32 nextdir32; + if (!SeekOK(tif, *nextdir) || + !ReadOK(tif, &dircount, sizeof (uint16))) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count", + tif->tif_name); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + if (off != NULL) + *off = TIFFSeekFile(tif, + dircount*12, SEEK_CUR); + else + (void) TIFFSeekFile(tif, + dircount*12, SEEK_CUR); + if (!ReadOK(tif, &nextdir32, sizeof (uint32))) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link", + tif->tif_name); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&nextdir32); + *nextdir=nextdir32; + } + else + { + uint64 dircount64; + uint16 dircount16; + if (!SeekOK(tif, *nextdir) || + !ReadOK(tif, &dircount64, sizeof (uint64))) { + TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count", + tif->tif_name); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8(&dircount64); + if (dircount64>0xFFFF) + { + TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count"); + return(0); + } + dircount16 = (uint16)dircount64; + if (off != NULL) + *off = TIFFSeekFile(tif, + dircount16*20, SEEK_CUR); + else + (void) TIFFSeekFile(tif, + dircount16*20, SEEK_CUR); + if (!ReadOK(tif, nextdir, sizeof (uint64))) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Error fetching directory link", + tif->tif_name); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8(nextdir); + } + return (1); + } } /* @@ -1470,16 +1566,28 @@ TIFFAdvanceDirectory(TIFF* tif, uint64* nextdir, uint64* off) uint16 TIFFNumberOfDirectories(TIFF* tif) { - uint64 nextdir; - uint16 n; - if (!(tif->tif_flags&TIFF_BIGTIFF)) - nextdir = tif->tif_header.classic.tiff_diroff; - else - nextdir = tif->tif_header.big.tiff_diroff; - n = 0; - while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL)) - n++; - return (n); + static const char module[] = "TIFFNumberOfDirectories"; + uint64 nextdir; + uint16 n; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + nextdir = tif->tif_header.classic.tiff_diroff; + else + nextdir = tif->tif_header.big.tiff_diroff; + n = 0; + while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL)) + { + if (n != 65535) { + ++n; + } + else + { + TIFFErrorExt(tif->tif_clientdata, module, + "Directory count exceeded 65535 limit," + " giving up on counting."); + return (65535); + } + } + return (n); } /* @@ -1489,29 +1597,29 @@ TIFFNumberOfDirectories(TIFF* tif) int TIFFSetDirectory(TIFF* tif, uint16 dirn) { - uint64 nextdir; - uint16 n; + uint64 nextdir; + uint16 n; - if (!(tif->tif_flags&TIFF_BIGTIFF)) - nextdir = tif->tif_header.classic.tiff_diroff; - else - nextdir = tif->tif_header.big.tiff_diroff; - for (n = dirn; n > 0 && nextdir != 0; n--) - if (!TIFFAdvanceDirectory(tif, &nextdir, NULL)) - return (0); - tif->tif_nextdiroff = nextdir; - /* - * Set curdir to the actual directory index. The - * -1 is because TIFFReadDirectory will increment - * tif_curdir after successfully reading the directory. - */ - tif->tif_curdir = (dirn - n) - 1; - /* - * Reset tif_dirnumber counter and start new list of seen directories. - * We need this to prevent IFD loops. - */ - tif->tif_dirnumber = 0; - return (TIFFReadDirectory(tif)); + if (!(tif->tif_flags&TIFF_BIGTIFF)) + nextdir = tif->tif_header.classic.tiff_diroff; + else + nextdir = tif->tif_header.big.tiff_diroff; + for (n = dirn; n > 0 && nextdir != 0; n--) + if (!TIFFAdvanceDirectory(tif, &nextdir, NULL)) + return (0); + tif->tif_nextdiroff = nextdir; + /* + * Set curdir to the actual directory index. The + * -1 is because TIFFReadDirectory will increment + * tif_curdir after successfully reading the directory. + */ + tif->tif_curdir = (dirn - n) - 1; + /* + * Reset tif_dirnumber counter and start new list of seen directories. + * We need this to prevent IFD loops. + */ + tif->tif_dirnumber = 0; + return (TIFFReadDirectory(tif)); } /* @@ -1523,13 +1631,13 @@ TIFFSetDirectory(TIFF* tif, uint16 dirn) int TIFFSetSubDirectory(TIFF* tif, uint64 diroff) { - tif->tif_nextdiroff = diroff; - /* - * Reset tif_dirnumber counter and start new list of seen directories. - * We need this to prevent IFD loops. - */ - tif->tif_dirnumber = 0; - return (TIFFReadDirectory(tif)); + tif->tif_nextdiroff = diroff; + /* + * Reset tif_dirnumber counter and start new list of seen directories. + * We need this to prevent IFD loops. + */ + tif->tif_dirnumber = 0; + return (TIFFReadDirectory(tif)); } /* @@ -1538,7 +1646,7 @@ TIFFSetSubDirectory(TIFF* tif, uint64 diroff) uint64 TIFFCurrentDirOffset(TIFF* tif) { - return (tif->tif_diroff); + return (tif->tif_diroff); } /* @@ -1548,7 +1656,7 @@ TIFFCurrentDirOffset(TIFF* tif) int TIFFLastDirectory(TIFF* tif) { - return (tif->tif_nextdiroff == 0); + return (tif->tif_nextdiroff == 0); } /* @@ -1557,96 +1665,96 @@ TIFFLastDirectory(TIFF* tif) int TIFFUnlinkDirectory(TIFF* tif, uint16 dirn) { - static const char module[] = "TIFFUnlinkDirectory"; - uint64 nextdir; - uint64 off; - uint16 n; + static const char module[] = "TIFFUnlinkDirectory"; + uint64 nextdir; + uint64 off; + uint16 n; - if (tif->tif_mode == O_RDONLY) { - TIFFErrorExt(tif->tif_clientdata, module, + if (tif->tif_mode == O_RDONLY) { + TIFFErrorExt(tif->tif_clientdata, module, "Can not unlink directory in read-only file"); - return (0); - } - /* - * Go to the directory before the one we want - * to unlink and nab the offset of the link - * field we'll need to patch. - */ - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - nextdir = tif->tif_header.classic.tiff_diroff; - off = 4; - } - else - { - nextdir = tif->tif_header.big.tiff_diroff; - off = 8; - } - for (n = dirn-1; n > 0; n--) { - if (nextdir == 0) { - TIFFErrorExt(tif->tif_clientdata, module, "Directory %d does not exist", dirn); - return (0); - } - if (!TIFFAdvanceDirectory(tif, &nextdir, &off)) - return (0); - } - /* - * Advance to the directory to be unlinked and fetch - * the offset of the directory that follows. - */ - if (!TIFFAdvanceDirectory(tif, &nextdir, NULL)) - return (0); - /* - * Go back and patch the link field of the preceding - * directory to point to the offset of the directory - * that follows. - */ - (void) TIFFSeekFile(tif, off, SEEK_SET); - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - uint32 nextdir32; - nextdir32=(uint32)nextdir; - assert((uint64)nextdir32==nextdir); - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong(&nextdir32); - if (!WriteOK(tif, &nextdir32, sizeof (uint32))) { - TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); - return (0); - } - } - else - { - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(&nextdir); - if (!WriteOK(tif, &nextdir, sizeof (uint64))) { - TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); - return (0); - } - } - /* - * Leave directory state setup safely. We don't have - * facilities for doing inserting and removing directories, - * so it's safest to just invalidate everything. This - * means that the caller can only append to the directory - * chain. - */ - (*tif->tif_cleanup)(tif); - if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { - _TIFFfree(tif->tif_rawdata); - tif->tif_rawdata = NULL; - tif->tif_rawcc = 0; + return (0); + } + /* + * Go to the directory before the one we want + * to unlink and nab the offset of the link + * field we'll need to patch. + */ + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + nextdir = tif->tif_header.classic.tiff_diroff; + off = 4; + } + else + { + nextdir = tif->tif_header.big.tiff_diroff; + off = 8; + } + for (n = dirn-1; n > 0; n--) { + if (nextdir == 0) { + TIFFErrorExt(tif->tif_clientdata, module, "Directory %d does not exist", dirn); + return (0); + } + if (!TIFFAdvanceDirectory(tif, &nextdir, &off)) + return (0); + } + /* + * Advance to the directory to be unlinked and fetch + * the offset of the directory that follows. + */ + if (!TIFFAdvanceDirectory(tif, &nextdir, NULL)) + return (0); + /* + * Go back and patch the link field of the preceding + * directory to point to the offset of the directory + * that follows. + */ + (void) TIFFSeekFile(tif, off, SEEK_SET); + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + uint32 nextdir32; + nextdir32=(uint32)nextdir; + assert((uint64)nextdir32==nextdir); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&nextdir32); + if (!WriteOK(tif, &nextdir32, sizeof (uint32))) { + TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); + return (0); + } + } + else + { + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8(&nextdir); + if (!WriteOK(tif, &nextdir, sizeof (uint64))) { + TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); + return (0); + } + } + /* + * Leave directory state setup safely. We don't have + * facilities for doing inserting and removing directories, + * so it's safest to just invalidate everything. This + * means that the caller can only append to the directory + * chain. + */ + (*tif->tif_cleanup)(tif); + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = NULL; + tif->tif_rawcc = 0; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = 0; - } - tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP|TIFF_POSTENCODE|TIFF_BUF4WRITE); - TIFFFreeDirectory(tif); - TIFFDefaultDirectory(tif); - tif->tif_diroff = 0; /* force link on next write */ - tif->tif_nextdiroff = 0; /* next write must be at end */ - tif->tif_curoff = 0; - tif->tif_row = (uint32) -1; - tif->tif_curstrip = (uint32) -1; - return (1); + } + tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP|TIFF_POSTENCODE|TIFF_BUF4WRITE); + TIFFFreeDirectory(tif); + TIFFDefaultDirectory(tif); + tif->tif_diroff = 0; /* force link on next write */ + tif->tif_nextdiroff = 0; /* next write must be at end */ + tif->tif_curoff = 0; + tif->tif_row = (uint32) -1; + tif->tif_curstrip = (uint32) -1; + return (1); } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_dir.h b/3rdparty/libtiff/tif_dir.h index 091037c35e..5a38076733 100644 --- a/3rdparty/libtiff/tif_dir.h +++ b/3rdparty/libtiff/tif_dir.h @@ -1,26 +1,26 @@ -/* $Id: tif_dir.h,v 1.54 2011-02-18 20:53:05 fwarmerdam Exp $ */ +/* $Id: tif_dir.h,v 1.55 2017-06-01 12:44:04 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -31,9 +31,9 @@ */ typedef struct { - const TIFFField *info; - int count; - void *value; + const TIFFField *info; + int count; + void *value; } TIFFTagValue; /* @@ -48,14 +48,14 @@ typedef struct { * it is left-justified in the offset field. */ typedef struct { - uint16 tdir_tag; /* see below */ - uint16 tdir_type; /* data type; see below */ - uint64 tdir_count; /* number of items; length in spec */ - union { - uint16 toff_short; - uint32 toff_long; - uint64 toff_long8; - } tdir_offset; /* either offset or the data itself if fits */ + uint16 tdir_tag; /* see below */ + uint16 tdir_type; /* data type; see below */ + uint64 tdir_count; /* number of items; length in spec */ + union { + uint16 toff_short; + uint32 toff_long; + uint64 toff_long8; + } tdir_offset; /* either offset or the data itself if fits */ } TIFFDirEntry; /* @@ -63,58 +63,58 @@ typedef struct { */ typedef struct { #define FIELD_SETLONGS 4 - /* bit vector of fields that are set */ - unsigned long td_fieldsset[FIELD_SETLONGS]; + /* bit vector of fields that are set */ + unsigned long td_fieldsset[FIELD_SETLONGS]; - uint32 td_imagewidth, td_imagelength, td_imagedepth; - uint32 td_tilewidth, td_tilelength, td_tiledepth; - uint32 td_subfiletype; - uint16 td_bitspersample; - uint16 td_sampleformat; - uint16 td_compression; - uint16 td_photometric; - uint16 td_threshholding; - uint16 td_fillorder; - uint16 td_orientation; - uint16 td_samplesperpixel; - uint32 td_rowsperstrip; - uint16 td_minsamplevalue, td_maxsamplevalue; - double* td_sminsamplevalue; - double* td_smaxsamplevalue; - float td_xresolution, td_yresolution; - uint16 td_resolutionunit; - uint16 td_planarconfig; - float td_xposition, td_yposition; - uint16 td_pagenumber[2]; - uint16* td_colormap[3]; - uint16 td_halftonehints[2]; - uint16 td_extrasamples; - uint16* td_sampleinfo; - /* even though the name is misleading, td_stripsperimage is the number - * of striles (=strips or tiles) per plane, and td_nstrips the total - * number of striles */ - uint32 td_stripsperimage; - uint32 td_nstrips; /* size of offset & bytecount arrays */ - uint64* td_stripoffset; - uint64* td_stripbytecount; - int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */ + uint32 td_imagewidth, td_imagelength, td_imagedepth; + uint32 td_tilewidth, td_tilelength, td_tiledepth; + uint32 td_subfiletype; + uint16 td_bitspersample; + uint16 td_sampleformat; + uint16 td_compression; + uint16 td_photometric; + uint16 td_threshholding; + uint16 td_fillorder; + uint16 td_orientation; + uint16 td_samplesperpixel; + uint32 td_rowsperstrip; + uint16 td_minsamplevalue, td_maxsamplevalue; + double* td_sminsamplevalue; + double* td_smaxsamplevalue; + float td_xresolution, td_yresolution; + uint16 td_resolutionunit; + uint16 td_planarconfig; + float td_xposition, td_yposition; + uint16 td_pagenumber[2]; + uint16* td_colormap[3]; + uint16 td_halftonehints[2]; + uint16 td_extrasamples; + uint16* td_sampleinfo; + /* even though the name is misleading, td_stripsperimage is the number + * of striles (=strips or tiles) per plane, and td_nstrips the total + * number of striles */ + uint32 td_stripsperimage; + uint32 td_nstrips; /* size of offset & bytecount arrays */ + uint64* td_stripoffset; + uint64* td_stripbytecount; + int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */ #if defined(DEFER_STRILE_LOAD) TIFFDirEntry td_stripoffset_entry; /* for deferred loading */ TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */ #endif - uint16 td_nsubifd; - uint64* td_subifd; - /* YCbCr parameters */ - uint16 td_ycbcrsubsampling[2]; - uint16 td_ycbcrpositioning; - /* Colorimetry parameters */ - uint16* td_transferfunction[3]; - float* td_refblackwhite; - /* CMYK parameters */ - int td_inknameslen; - char* td_inknames; + uint16 td_nsubifd; + uint64* td_subifd; + /* YCbCr parameters */ + uint16 td_ycbcrsubsampling[2]; + uint16 td_ycbcrpositioning; + /* Colorimetry parameters */ + uint16* td_transferfunction[3]; + float* td_refblackwhite; + /* CMYK parameters */ + int td_inknameslen; + char* td_inknames; - int td_customValueCount; + int td_customValueCount; TIFFTagValue *td_customValues; } TIFFDirectory; @@ -195,58 +195,58 @@ typedef struct { #define ResetFieldBit(fields, f) (fields[(f)/32] &= ~BITn(f)) typedef enum { - TIFF_SETGET_UNDEFINED = 0, - TIFF_SETGET_ASCII = 1, - TIFF_SETGET_UINT8 = 2, - TIFF_SETGET_SINT8 = 3, - TIFF_SETGET_UINT16 = 4, - TIFF_SETGET_SINT16 = 5, - TIFF_SETGET_UINT32 = 6, - TIFF_SETGET_SINT32 = 7, - TIFF_SETGET_UINT64 = 8, - TIFF_SETGET_SINT64 = 9, - TIFF_SETGET_FLOAT = 10, - TIFF_SETGET_DOUBLE = 11, - TIFF_SETGET_IFD8 = 12, - TIFF_SETGET_INT = 13, - TIFF_SETGET_UINT16_PAIR = 14, - TIFF_SETGET_C0_ASCII = 15, - TIFF_SETGET_C0_UINT8 = 16, - TIFF_SETGET_C0_SINT8 = 17, - TIFF_SETGET_C0_UINT16 = 18, - TIFF_SETGET_C0_SINT16 = 19, - TIFF_SETGET_C0_UINT32 = 20, - TIFF_SETGET_C0_SINT32 = 21, - TIFF_SETGET_C0_UINT64 = 22, - TIFF_SETGET_C0_SINT64 = 23, - TIFF_SETGET_C0_FLOAT = 24, - TIFF_SETGET_C0_DOUBLE = 25, - TIFF_SETGET_C0_IFD8 = 26, - TIFF_SETGET_C16_ASCII = 27, - TIFF_SETGET_C16_UINT8 = 28, - TIFF_SETGET_C16_SINT8 = 29, - TIFF_SETGET_C16_UINT16 = 30, - TIFF_SETGET_C16_SINT16 = 31, - TIFF_SETGET_C16_UINT32 = 32, - TIFF_SETGET_C16_SINT32 = 33, - TIFF_SETGET_C16_UINT64 = 34, - TIFF_SETGET_C16_SINT64 = 35, - TIFF_SETGET_C16_FLOAT = 36, - TIFF_SETGET_C16_DOUBLE = 37, - TIFF_SETGET_C16_IFD8 = 38, - TIFF_SETGET_C32_ASCII = 39, - TIFF_SETGET_C32_UINT8 = 40, - TIFF_SETGET_C32_SINT8 = 41, - TIFF_SETGET_C32_UINT16 = 42, - TIFF_SETGET_C32_SINT16 = 43, - TIFF_SETGET_C32_UINT32 = 44, - TIFF_SETGET_C32_SINT32 = 45, - TIFF_SETGET_C32_UINT64 = 46, - TIFF_SETGET_C32_SINT64 = 47, - TIFF_SETGET_C32_FLOAT = 48, - TIFF_SETGET_C32_DOUBLE = 49, - TIFF_SETGET_C32_IFD8 = 50, - TIFF_SETGET_OTHER = 51 + TIFF_SETGET_UNDEFINED = 0, + TIFF_SETGET_ASCII = 1, + TIFF_SETGET_UINT8 = 2, + TIFF_SETGET_SINT8 = 3, + TIFF_SETGET_UINT16 = 4, + TIFF_SETGET_SINT16 = 5, + TIFF_SETGET_UINT32 = 6, + TIFF_SETGET_SINT32 = 7, + TIFF_SETGET_UINT64 = 8, + TIFF_SETGET_SINT64 = 9, + TIFF_SETGET_FLOAT = 10, + TIFF_SETGET_DOUBLE = 11, + TIFF_SETGET_IFD8 = 12, + TIFF_SETGET_INT = 13, + TIFF_SETGET_UINT16_PAIR = 14, + TIFF_SETGET_C0_ASCII = 15, + TIFF_SETGET_C0_UINT8 = 16, + TIFF_SETGET_C0_SINT8 = 17, + TIFF_SETGET_C0_UINT16 = 18, + TIFF_SETGET_C0_SINT16 = 19, + TIFF_SETGET_C0_UINT32 = 20, + TIFF_SETGET_C0_SINT32 = 21, + TIFF_SETGET_C0_UINT64 = 22, + TIFF_SETGET_C0_SINT64 = 23, + TIFF_SETGET_C0_FLOAT = 24, + TIFF_SETGET_C0_DOUBLE = 25, + TIFF_SETGET_C0_IFD8 = 26, + TIFF_SETGET_C16_ASCII = 27, + TIFF_SETGET_C16_UINT8 = 28, + TIFF_SETGET_C16_SINT8 = 29, + TIFF_SETGET_C16_UINT16 = 30, + TIFF_SETGET_C16_SINT16 = 31, + TIFF_SETGET_C16_UINT32 = 32, + TIFF_SETGET_C16_SINT32 = 33, + TIFF_SETGET_C16_UINT64 = 34, + TIFF_SETGET_C16_SINT64 = 35, + TIFF_SETGET_C16_FLOAT = 36, + TIFF_SETGET_C16_DOUBLE = 37, + TIFF_SETGET_C16_IFD8 = 38, + TIFF_SETGET_C32_ASCII = 39, + TIFF_SETGET_C32_UINT8 = 40, + TIFF_SETGET_C32_SINT8 = 41, + TIFF_SETGET_C32_UINT16 = 42, + TIFF_SETGET_C32_SINT16 = 43, + TIFF_SETGET_C32_UINT32 = 44, + TIFF_SETGET_C32_SINT32 = 45, + TIFF_SETGET_C32_UINT64 = 46, + TIFF_SETGET_C32_SINT64 = 47, + TIFF_SETGET_C32_FLOAT = 48, + TIFF_SETGET_C32_DOUBLE = 49, + TIFF_SETGET_C32_IFD8 = 50, + TIFF_SETGET_OTHER = 51 } TIFFSetGetFieldType; #if defined(__cplusplus) @@ -258,39 +258,40 @@ extern const TIFFFieldArray* _TIFFGetExifFields(void); extern void _TIFFSetupFields(TIFF* tif, const TIFFFieldArray* infoarray); extern void _TIFFPrintFieldInfo(TIFF*, FILE*); -extern int _TIFFFillStriles(TIFF*); +extern int _TIFFFillStriles(TIFF*); typedef enum { - tfiatImage, - tfiatExif, - tfiatOther + tfiatImage, + tfiatExif, + tfiatOther } TIFFFieldArrayType; struct _TIFFFieldArray { - TIFFFieldArrayType type; /* array type, will be used to determine if IFD is image and such */ - uint32 allocated_size; /* 0 if array is constant, other if modified by future definition extension support */ - uint32 count; /* number of elements in fields array */ - TIFFField* fields; /* actual field info */ + TIFFFieldArrayType type; /* array type, will be used to determine if IFD is image and such */ + uint32 allocated_size; /* 0 if array is constant, other if modified by future definition extension support */ + uint32 count; /* number of elements in fields array */ + TIFFField* fields; /* actual field info */ }; struct _TIFFField { - uint32 field_tag; /* field's tag */ - short field_readcount; /* read count/TIFF_VARIABLE/TIFF_SPP */ - short field_writecount; /* write count/TIFF_VARIABLE */ - TIFFDataType field_type; /* type of associated data */ - uint32 reserved; /* reserved for future extension */ - TIFFSetGetFieldType set_field_type; /* type to be passed to TIFFSetField */ - TIFFSetGetFieldType get_field_type; /* type to be passed to TIFFGetField */ - unsigned short field_bit; /* bit in fieldsset bit vector */ - unsigned char field_oktochange; /* if true, can change while writing */ - unsigned char field_passcount; /* if true, pass dir count on set */ - char* field_name; /* ASCII name */ - TIFFFieldArray* field_subfields; /* if field points to child ifds, child ifd field definition array */ + uint32 field_tag; /* field's tag */ + short field_readcount; /* read count/TIFF_VARIABLE/TIFF_SPP */ + short field_writecount; /* write count/TIFF_VARIABLE */ + TIFFDataType field_type; /* type of associated data */ + uint32 reserved; /* reserved for future extension */ + TIFFSetGetFieldType set_field_type; /* type to be passed to TIFFSetField */ + TIFFSetGetFieldType get_field_type; /* type to be passed to TIFFGetField */ + unsigned short field_bit; /* bit in fieldsset bit vector */ + unsigned char field_oktochange; /* if true, can change while writing */ + unsigned char field_passcount; /* if true, pass dir count on set */ + char* field_name; /* ASCII name */ + TIFFFieldArray* field_subfields; /* if field points to child ifds, child ifd field definition array */ }; extern int _TIFFMergeFields(TIFF*, const TIFFField[], uint32); extern const TIFFField* _TIFFFindOrRegisterField(TIFF *, uint32, TIFFDataType); extern TIFFField* _TIFFCreateAnonField(TIFF *, uint32, TIFFDataType); +extern int _TIFFCheckFieldIsValidForCodec(TIFF *tif, ttag_t tag); #if defined(__cplusplus) } diff --git a/3rdparty/libtiff/tif_dirinfo.c b/3rdparty/libtiff/tif_dirinfo.c index af5c580c98..4904f540e5 100644 --- a/3rdparty/libtiff/tif_dirinfo.c +++ b/3rdparty/libtiff/tif_dirinfo.c @@ -1,4 +1,4 @@ -/* $Id: tif_dirinfo.c,v 1.114 2011-05-17 00:21:17 fwarmerdam Exp $ */ +/* $Id: tif_dirinfo.c,v 1.127 2017-06-01 12:44:04 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -37,232 +37,256 @@ * * NOTE: The second field (field_readcount) and third field (field_writecount) * sometimes use the values TIFF_VARIABLE (-1), TIFF_VARIABLE2 (-3) - * and TIFFTAG_SPP (-2). The macros should be used but would throw off - * the formatting of the code, so please interprete the -1, -2 and -3 + * and TIFF_SPP (-2). The macros should be used but would throw off + * the formatting of the code, so please interpret the -1, -2 and -3 * values accordingly. */ -static TIFFFieldArray tiffFieldArray; -static TIFFFieldArray exifFieldArray; +/* const object should be initialized */ +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4132 ) +#endif +static const TIFFFieldArray tiffFieldArray; +static const TIFFFieldArray exifFieldArray; +#ifdef _MSC_VER +#pragma warning( pop ) +#endif -static TIFFField +static const TIFFField tiffFields[] = { - { TIFFTAG_SUBFILETYPE, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_SUBFILETYPE, 1, 0, "SubfileType", NULL }, - { TIFFTAG_OSUBFILETYPE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_SUBFILETYPE, 1, 0, "OldSubfileType", NULL }, - { TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_IMAGEDIMENSIONS, 0, 0, "ImageWidth", NULL }, - { TIFFTAG_IMAGELENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_IMAGEDIMENSIONS, 1, 0, "ImageLength", NULL }, - { TIFFTAG_BITSPERSAMPLE, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_BITSPERSAMPLE, 0, 0, "BitsPerSample", NULL }, - { TIFFTAG_COMPRESSION, -1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_COMPRESSION, 0, 0, "Compression", NULL }, - { TIFFTAG_PHOTOMETRIC, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_PHOTOMETRIC, 0, 0, "PhotometricInterpretation", NULL }, - { TIFFTAG_THRESHHOLDING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_THRESHHOLDING, 1, 0, "Threshholding", NULL }, - { TIFFTAG_CELLWIDTH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "CellWidth", NULL }, - { TIFFTAG_CELLLENGTH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "CellLength", NULL }, - { TIFFTAG_FILLORDER, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_FILLORDER, 0, 0, "FillOrder", NULL }, - { TIFFTAG_DOCUMENTNAME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DocumentName", NULL }, - { TIFFTAG_IMAGEDESCRIPTION, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageDescription", NULL }, - { TIFFTAG_MAKE, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Make", NULL }, - { TIFFTAG_MODEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Model", NULL }, - { TIFFTAG_STRIPOFFSETS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPOFFSETS, 0, 0, "StripOffsets", NULL }, - { TIFFTAG_ORIENTATION, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_ORIENTATION, 0, 0, "Orientation", NULL }, - { TIFFTAG_SAMPLESPERPIXEL, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_SAMPLESPERPIXEL, 0, 0, "SamplesPerPixel", NULL }, - { TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_ROWSPERSTRIP, 0, 0, "RowsPerStrip", NULL }, - { TIFFTAG_STRIPBYTECOUNTS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPBYTECOUNTS, 0, 0, "StripByteCounts", NULL }, - { TIFFTAG_MINSAMPLEVALUE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_MINSAMPLEVALUE, 1, 0, "MinSampleValue", NULL }, - { TIFFTAG_MAXSAMPLEVALUE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_MAXSAMPLEVALUE, 1, 0, "MaxSampleValue", NULL }, - { TIFFTAG_XRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_RESOLUTION, 1, 0, "XResolution", NULL }, - { TIFFTAG_YRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_RESOLUTION, 1, 0, "YResolution", NULL }, - { TIFFTAG_PLANARCONFIG, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_PLANARCONFIG, 0, 0, "PlanarConfiguration", NULL }, - { TIFFTAG_PAGENAME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PageName", NULL }, - { TIFFTAG_XPOSITION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_POSITION, 1, 0, "XPosition", NULL }, - { TIFFTAG_YPOSITION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_POSITION, 1, 0, "YPosition", NULL }, - { TIFFTAG_FREEOFFSETS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 0, 0, "FreeOffsets", NULL }, - { TIFFTAG_FREEBYTECOUNTS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 0, 0, "FreeByteCounts", NULL }, - { TIFFTAG_GRAYRESPONSEUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "GrayResponseUnit", NULL }, - { TIFFTAG_GRAYRESPONSECURVE, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "GrayResponseCurve", NULL }, - { TIFFTAG_RESOLUTIONUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_RESOLUTIONUNIT, 1, 0, "ResolutionUnit", NULL }, - { TIFFTAG_PAGENUMBER, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_PAGENUMBER, 1, 0, "PageNumber", NULL }, - { TIFFTAG_COLORRESPONSEUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "ColorResponseUnit", NULL }, - { TIFFTAG_TRANSFERFUNCTION, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_OTHER, TIFF_SETGET_UNDEFINED, FIELD_TRANSFERFUNCTION, 1, 0, "TransferFunction", NULL }, - { TIFFTAG_SOFTWARE, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Software", NULL }, - { TIFFTAG_DATETIME, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTime", NULL }, - { TIFFTAG_ARTIST, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Artist", NULL }, - { TIFFTAG_HOSTCOMPUTER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "HostComputer", NULL }, - { TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WhitePoint", NULL }, - { TIFFTAG_PRIMARYCHROMATICITIES, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PrimaryChromaticities", NULL }, - { TIFFTAG_COLORMAP, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_OTHER, TIFF_SETGET_UNDEFINED, FIELD_COLORMAP, 1, 0, "ColorMap", NULL }, - { TIFFTAG_HALFTONEHINTS, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_HALFTONEHINTS, 1, 0, "HalftoneHints", NULL }, - { TIFFTAG_TILEWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_TILEDIMENSIONS, 0, 0, "TileWidth", NULL }, - { TIFFTAG_TILELENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_TILEDIMENSIONS, 0, 0, "TileLength", NULL }, - { TIFFTAG_TILEOFFSETS, -1, 1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPOFFSETS, 0, 0, "TileOffsets", NULL }, - { TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPBYTECOUNTS, 0, 0, "TileByteCounts", NULL }, - { TIFFTAG_SUBIFD, -1, -1, TIFF_IFD8, 0, TIFF_SETGET_C16_IFD8, TIFF_SETGET_UNDEFINED, FIELD_SUBIFD, 1, 1, "SubIFD", &tiffFieldArray }, - { TIFFTAG_INKSET, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "InkSet", NULL }, - { TIFFTAG_INKNAMES, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_C16_ASCII, TIFF_SETGET_UNDEFINED, FIELD_INKNAMES, 1, 1, "InkNames", NULL }, - { TIFFTAG_NUMBEROFINKS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "NumberOfInks", NULL }, - { TIFFTAG_DOTRANGE, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DotRange", NULL }, - { TIFFTAG_TARGETPRINTER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TargetPrinter", NULL }, - { TIFFTAG_EXTRASAMPLES, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_EXTRASAMPLES, 0, 1, "ExtraSamples", NULL }, - { TIFFTAG_SAMPLEFORMAT, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_SAMPLEFORMAT, 0, 0, "SampleFormat", NULL }, - { TIFFTAG_SMINSAMPLEVALUE, -2, -1, TIFF_ANY, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_SMINSAMPLEVALUE, 1, 0, "SMinSampleValue", NULL }, - { TIFFTAG_SMAXSAMPLEVALUE, -2, -1, TIFF_ANY, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_SMAXSAMPLEVALUE, 1, 0, "SMaxSampleValue", NULL }, - { TIFFTAG_CLIPPATH, -1, -3, TIFF_BYTE, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ClipPath", NULL }, - { TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SLONG, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "XClipPathUnits", NULL }, - { TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SBYTE, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "XClipPathUnits", NULL }, - { TIFFTAG_YCLIPPATHUNITS, 1, 1, TIFF_SLONG, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "YClipPathUnits", NULL }, - { TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "YCbCrCoefficients", NULL }, - { TIFFTAG_YCBCRSUBSAMPLING, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_YCBCRSUBSAMPLING, 0, 0, "YCbCrSubsampling", NULL }, - { TIFFTAG_YCBCRPOSITIONING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_YCBCRPOSITIONING, 0, 0, "YCbCrPositioning", NULL }, - { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_REFBLACKWHITE, 1, 0, "ReferenceBlackWhite", NULL }, - { TIFFTAG_XMLPACKET, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "XMLPacket", NULL }, - /* begin SGI tags */ - { TIFFTAG_MATTEING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_EXTRASAMPLES, 0, 0, "Matteing", NULL }, - { TIFFTAG_DATATYPE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_SAMPLEFORMAT, 0, 0, "DataType", NULL }, - { TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_IMAGEDEPTH, 0, 0, "ImageDepth", NULL }, - { TIFFTAG_TILEDEPTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_TILEDEPTH, 0, 0, "TileDepth", NULL }, - /* end SGI tags */ - /* begin Pixar tags */ - { TIFFTAG_PIXAR_IMAGEFULLWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageFullWidth", NULL }, - { TIFFTAG_PIXAR_IMAGEFULLLENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageFullLength", NULL }, - { TIFFTAG_PIXAR_TEXTUREFORMAT, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TextureFormat", NULL }, - { TIFFTAG_PIXAR_WRAPMODES, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TextureWrapModes", NULL }, - { TIFFTAG_PIXAR_FOVCOT, 1, 1, TIFF_FLOAT, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FieldOfViewCotangent", NULL }, - { TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN, 16, 16, TIFF_FLOAT, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MatrixWorldToScreen", NULL }, - { TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA, 16, 16, TIFF_FLOAT, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MatrixWorldToCamera", NULL }, - { TIFFTAG_COPYRIGHT, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Copyright", NULL }, - /* end Pixar tags */ - { TIFFTAG_RICHTIFFIPTC, -3, -3, TIFF_LONG, 0, TIFF_SETGET_C32_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "RichTIFFIPTC", NULL }, - { TIFFTAG_PHOTOSHOP, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "Photoshop", NULL }, - { TIFFTAG_EXIFIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "EXIFIFDOffset", &exifFieldArray }, - { TIFFTAG_ICCPROFILE, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ICC Profile", NULL }, - { TIFFTAG_GPSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "GPSIFDOffset", NULL }, - { TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvParams", NULL }, - { TIFFTAG_FAXSUBADDRESS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_ASCII, FIELD_CUSTOM, TRUE, FALSE, "FaxSubAddress", NULL }, - { TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvTime", NULL }, - { TIFFTAG_FAXDCS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_ASCII, FIELD_CUSTOM, TRUE, FALSE, "FaxDcs", NULL }, - { TIFFTAG_STONITS, 1, 1, TIFF_DOUBLE, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "StoNits", NULL }, - { TIFFTAG_INTEROPERABILITYIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "InteroperabilityIFDOffset", NULL }, - /* begin DNG tags */ - { TIFFTAG_DNGVERSION, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DNGVersion", NULL }, - { TIFFTAG_DNGBACKWARDVERSION, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DNGBackwardVersion", NULL }, - { TIFFTAG_UNIQUECAMERAMODEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "UniqueCameraModel", NULL }, - { TIFFTAG_LOCALIZEDCAMERAMODEL, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "LocalizedCameraModel", NULL }, - { TIFFTAG_CFAPLANECOLOR, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CFAPlaneColor", NULL }, - { TIFFTAG_CFALAYOUT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CFALayout", NULL }, - { TIFFTAG_LINEARIZATIONTABLE, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "LinearizationTable", NULL }, - { TIFFTAG_BLACKLEVELREPEATDIM, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BlackLevelRepeatDim", NULL }, - { TIFFTAG_BLACKLEVEL, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "BlackLevel", NULL }, - { TIFFTAG_BLACKLEVELDELTAH, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "BlackLevelDeltaH", NULL }, - { TIFFTAG_BLACKLEVELDELTAV, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "BlackLevelDeltaV", NULL }, - { TIFFTAG_WHITELEVEL, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "WhiteLevel", NULL }, - { TIFFTAG_DEFAULTSCALE, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DefaultScale", NULL }, - { TIFFTAG_BESTQUALITYSCALE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BestQualityScale", NULL }, - { TIFFTAG_DEFAULTCROPORIGIN, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DefaultCropOrigin", NULL }, - { TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DefaultCropSize", NULL }, - { TIFFTAG_COLORMATRIX1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ColorMatrix1", NULL }, - { TIFFTAG_COLORMATRIX2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ColorMatrix2", NULL }, - { TIFFTAG_CAMERACALIBRATION1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CameraCalibration1", NULL }, - { TIFFTAG_CAMERACALIBRATION2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CameraCalibration2", NULL }, - { TIFFTAG_REDUCTIONMATRIX1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ReductionMatrix1", NULL }, - { TIFFTAG_REDUCTIONMATRIX2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ReductionMatrix2", NULL }, - { TIFFTAG_ANALOGBALANCE, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "AnalogBalance", NULL }, - { TIFFTAG_ASSHOTNEUTRAL, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "AsShotNeutral", NULL }, - { TIFFTAG_ASSHOTWHITEXY, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "AsShotWhiteXY", NULL }, - { TIFFTAG_BASELINEEXPOSURE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BaselineExposure", NULL }, - { TIFFTAG_BASELINENOISE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BaselineNoise", NULL }, - { TIFFTAG_BASELINESHARPNESS, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BaselineSharpness", NULL }, - { TIFFTAG_BAYERGREENSPLIT, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BayerGreenSplit", NULL }, - { TIFFTAG_LINEARRESPONSELIMIT, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "LinearResponseLimit", NULL }, - { TIFFTAG_CAMERASERIALNUMBER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CameraSerialNumber", NULL }, - { TIFFTAG_LENSINFO, 4, 4, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "LensInfo", NULL }, - { TIFFTAG_CHROMABLURRADIUS, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ChromaBlurRadius", NULL }, - { TIFFTAG_ANTIALIASSTRENGTH, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "AntiAliasStrength", NULL }, - { TIFFTAG_SHADOWSCALE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ShadowScale", NULL }, - { TIFFTAG_DNGPRIVATEDATA, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "DNGPrivateData", NULL }, - { TIFFTAG_MAKERNOTESAFETY, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "MakerNoteSafety", NULL }, - { TIFFTAG_CALIBRATIONILLUMINANT1, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CalibrationIlluminant1", NULL }, - { TIFFTAG_CALIBRATIONILLUMINANT2, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CalibrationIlluminant2", NULL }, - { TIFFTAG_RAWDATAUNIQUEID, 16, 16, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "RawDataUniqueID", NULL }, - { TIFFTAG_ORIGINALRAWFILENAME, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OriginalRawFileName", NULL }, - { TIFFTAG_ORIGINALRAWFILEDATA, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "OriginalRawFileData", NULL }, - { TIFFTAG_ACTIVEAREA, 4, 4, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ActiveArea", NULL }, - { TIFFTAG_MASKEDAREAS, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "MaskedAreas", NULL }, - { TIFFTAG_ASSHOTICCPROFILE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "AsShotICCProfile", NULL }, - { TIFFTAG_ASSHOTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "AsShotPreProfileMatrix", NULL }, - { TIFFTAG_CURRENTICCPROFILE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CurrentICCProfile", NULL }, - { TIFFTAG_CURRENTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CurrentPreProfileMatrix", NULL }, - /* end DNG tags */ - /* begin pseudo tags */ - { TIFFTAG_PERSAMPLE, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "PerSample", NULL}, + { TIFFTAG_SUBFILETYPE, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_SUBFILETYPE, 1, 0, "SubfileType", NULL }, + { TIFFTAG_OSUBFILETYPE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_SUBFILETYPE, 1, 0, "OldSubfileType", NULL }, + { TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_IMAGEDIMENSIONS, 0, 0, "ImageWidth", NULL }, + { TIFFTAG_IMAGELENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_IMAGEDIMENSIONS, 1, 0, "ImageLength", NULL }, + { TIFFTAG_BITSPERSAMPLE, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_BITSPERSAMPLE, 0, 0, "BitsPerSample", NULL }, + { TIFFTAG_COMPRESSION, -1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_COMPRESSION, 0, 0, "Compression", NULL }, + { TIFFTAG_PHOTOMETRIC, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_PHOTOMETRIC, 0, 0, "PhotometricInterpretation", NULL }, + { TIFFTAG_THRESHHOLDING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_THRESHHOLDING, 1, 0, "Threshholding", NULL }, + { TIFFTAG_CELLWIDTH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "CellWidth", NULL }, + { TIFFTAG_CELLLENGTH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "CellLength", NULL }, + { TIFFTAG_FILLORDER, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_FILLORDER, 0, 0, "FillOrder", NULL }, + { TIFFTAG_DOCUMENTNAME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DocumentName", NULL }, + { TIFFTAG_IMAGEDESCRIPTION, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageDescription", NULL }, + { TIFFTAG_MAKE, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Make", NULL }, + { TIFFTAG_MODEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Model", NULL }, + { TIFFTAG_STRIPOFFSETS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPOFFSETS, 0, 0, "StripOffsets", NULL }, + { TIFFTAG_ORIENTATION, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_ORIENTATION, 0, 0, "Orientation", NULL }, + { TIFFTAG_SAMPLESPERPIXEL, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_SAMPLESPERPIXEL, 0, 0, "SamplesPerPixel", NULL }, + { TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_ROWSPERSTRIP, 0, 0, "RowsPerStrip", NULL }, + { TIFFTAG_STRIPBYTECOUNTS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPBYTECOUNTS, 0, 0, "StripByteCounts", NULL }, + { TIFFTAG_MINSAMPLEVALUE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_MINSAMPLEVALUE, 1, 0, "MinSampleValue", NULL }, + { TIFFTAG_MAXSAMPLEVALUE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_MAXSAMPLEVALUE, 1, 0, "MaxSampleValue", NULL }, + { TIFFTAG_XRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_RESOLUTION, 1, 0, "XResolution", NULL }, + { TIFFTAG_YRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_RESOLUTION, 1, 0, "YResolution", NULL }, + { TIFFTAG_PLANARCONFIG, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_PLANARCONFIG, 0, 0, "PlanarConfiguration", NULL }, + { TIFFTAG_PAGENAME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PageName", NULL }, + { TIFFTAG_XPOSITION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_POSITION, 1, 0, "XPosition", NULL }, + { TIFFTAG_YPOSITION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_POSITION, 1, 0, "YPosition", NULL }, + { TIFFTAG_FREEOFFSETS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 0, 0, "FreeOffsets", NULL }, + { TIFFTAG_FREEBYTECOUNTS, -1, -1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 0, 0, "FreeByteCounts", NULL }, + { TIFFTAG_GRAYRESPONSEUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "GrayResponseUnit", NULL }, + { TIFFTAG_GRAYRESPONSECURVE, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "GrayResponseCurve", NULL }, + { TIFFTAG_RESOLUTIONUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_RESOLUTIONUNIT, 1, 0, "ResolutionUnit", NULL }, + { TIFFTAG_PAGENUMBER, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_PAGENUMBER, 1, 0, "PageNumber", NULL }, + { TIFFTAG_COLORRESPONSEUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_IGNORE, 1, 0, "ColorResponseUnit", NULL }, + { TIFFTAG_TRANSFERFUNCTION, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_OTHER, TIFF_SETGET_UNDEFINED, FIELD_TRANSFERFUNCTION, 1, 0, "TransferFunction", NULL }, + { TIFFTAG_SOFTWARE, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Software", NULL }, + { TIFFTAG_DATETIME, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTime", NULL }, + { TIFFTAG_ARTIST, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Artist", NULL }, + { TIFFTAG_HOSTCOMPUTER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "HostComputer", NULL }, + { TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WhitePoint", NULL }, + { TIFFTAG_PRIMARYCHROMATICITIES, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PrimaryChromaticities", NULL }, + { TIFFTAG_COLORMAP, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_OTHER, TIFF_SETGET_UNDEFINED, FIELD_COLORMAP, 1, 0, "ColorMap", NULL }, + { TIFFTAG_HALFTONEHINTS, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_HALFTONEHINTS, 1, 0, "HalftoneHints", NULL }, + { TIFFTAG_TILEWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_TILEDIMENSIONS, 0, 0, "TileWidth", NULL }, + { TIFFTAG_TILELENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_TILEDIMENSIONS, 0, 0, "TileLength", NULL }, + { TIFFTAG_TILEOFFSETS, -1, 1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPOFFSETS, 0, 0, "TileOffsets", NULL }, + { TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_LONG8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_STRIPBYTECOUNTS, 0, 0, "TileByteCounts", NULL }, + { TIFFTAG_SUBIFD, -1, -1, TIFF_IFD8, 0, TIFF_SETGET_C16_IFD8, TIFF_SETGET_UNDEFINED, FIELD_SUBIFD, 1, 1, "SubIFD", (TIFFFieldArray*) &tiffFieldArray }, + { TIFFTAG_INKSET, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "InkSet", NULL }, + { TIFFTAG_INKNAMES, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_C16_ASCII, TIFF_SETGET_UNDEFINED, FIELD_INKNAMES, 1, 1, "InkNames", NULL }, + { TIFFTAG_NUMBEROFINKS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "NumberOfInks", NULL }, + { TIFFTAG_DOTRANGE, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DotRange", NULL }, + { TIFFTAG_TARGETPRINTER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TargetPrinter", NULL }, + { TIFFTAG_EXTRASAMPLES, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_EXTRASAMPLES, 0, 1, "ExtraSamples", NULL }, + { TIFFTAG_SAMPLEFORMAT, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_SAMPLEFORMAT, 0, 0, "SampleFormat", NULL }, + { TIFFTAG_SMINSAMPLEVALUE, -2, -1, TIFF_ANY, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_SMINSAMPLEVALUE, 1, 0, "SMinSampleValue", NULL }, + { TIFFTAG_SMAXSAMPLEVALUE, -2, -1, TIFF_ANY, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_SMAXSAMPLEVALUE, 1, 0, "SMaxSampleValue", NULL }, + { TIFFTAG_CLIPPATH, -1, -3, TIFF_BYTE, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ClipPath", NULL }, + { TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SLONG, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "XClipPathUnits", NULL }, + { TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SBYTE, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "XClipPathUnits", NULL }, + { TIFFTAG_YCLIPPATHUNITS, 1, 1, TIFF_SLONG, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "YClipPathUnits", NULL }, + { TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "YCbCrCoefficients", NULL }, + { TIFFTAG_YCBCRSUBSAMPLING, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_UINT16_PAIR, TIFF_SETGET_UNDEFINED, FIELD_YCBCRSUBSAMPLING, 0, 0, "YCbCrSubsampling", NULL }, + { TIFFTAG_YCBCRPOSITIONING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_YCBCRPOSITIONING, 0, 0, "YCbCrPositioning", NULL }, + { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_REFBLACKWHITE, 1, 0, "ReferenceBlackWhite", NULL }, + { TIFFTAG_XMLPACKET, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "XMLPacket", NULL }, + /* begin SGI tags */ + { TIFFTAG_MATTEING, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_EXTRASAMPLES, 0, 0, "Matteing", NULL }, + { TIFFTAG_DATATYPE, -2, -1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_SAMPLEFORMAT, 0, 0, "DataType", NULL }, + { TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_IMAGEDEPTH, 0, 0, "ImageDepth", NULL }, + { TIFFTAG_TILEDEPTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_TILEDEPTH, 0, 0, "TileDepth", NULL }, + /* end SGI tags */ + /* begin Pixar tags */ + { TIFFTAG_PIXAR_IMAGEFULLWIDTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageFullWidth", NULL }, + { TIFFTAG_PIXAR_IMAGEFULLLENGTH, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageFullLength", NULL }, + { TIFFTAG_PIXAR_TEXTUREFORMAT, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TextureFormat", NULL }, + { TIFFTAG_PIXAR_WRAPMODES, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "TextureWrapModes", NULL }, + { TIFFTAG_PIXAR_FOVCOT, 1, 1, TIFF_FLOAT, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FieldOfViewCotangent", NULL }, + { TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN, 16, 16, TIFF_FLOAT, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MatrixWorldToScreen", NULL }, + { TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA, 16, 16, TIFF_FLOAT, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MatrixWorldToCamera", NULL }, + { TIFFTAG_CFAREPEATPATTERNDIM, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CFARepeatPatternDim", NULL }, + { TIFFTAG_CFAPATTERN, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CFAPattern" , NULL}, + { TIFFTAG_COPYRIGHT, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Copyright", NULL }, + /* end Pixar tags */ + { TIFFTAG_RICHTIFFIPTC, -3, -3, TIFF_LONG, 0, TIFF_SETGET_C32_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "RichTIFFIPTC", NULL }, + { TIFFTAG_PHOTOSHOP, -3, -3, TIFF_BYTE, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "Photoshop", NULL }, + { TIFFTAG_EXIFIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "EXIFIFDOffset", (TIFFFieldArray*) &exifFieldArray }, + { TIFFTAG_ICCPROFILE, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ICC Profile", NULL }, + { TIFFTAG_GPSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "GPSIFDOffset", NULL }, + { TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvParams", NULL }, + { TIFFTAG_FAXSUBADDRESS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_ASCII, FIELD_CUSTOM, TRUE, FALSE, "FaxSubAddress", NULL }, + { TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UINT32, FIELD_CUSTOM, TRUE, FALSE, "FaxRecvTime", NULL }, + { TIFFTAG_FAXDCS, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_ASCII, FIELD_CUSTOM, TRUE, FALSE, "FaxDcs", NULL }, + { TIFFTAG_STONITS, 1, 1, TIFF_DOUBLE, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "StoNits", NULL }, + { TIFFTAG_INTEROPERABILITYIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "InteroperabilityIFDOffset", NULL }, + /* begin DNG tags */ + { TIFFTAG_DNGVERSION, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DNGVersion", NULL }, + { TIFFTAG_DNGBACKWARDVERSION, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DNGBackwardVersion", NULL }, + { TIFFTAG_UNIQUECAMERAMODEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "UniqueCameraModel", NULL }, + { TIFFTAG_LOCALIZEDCAMERAMODEL, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "LocalizedCameraModel", NULL }, + { TIFFTAG_CFAPLANECOLOR, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CFAPlaneColor", NULL }, + { TIFFTAG_CFALAYOUT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CFALayout", NULL }, + { TIFFTAG_LINEARIZATIONTABLE, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "LinearizationTable", NULL }, + { TIFFTAG_BLACKLEVELREPEATDIM, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BlackLevelRepeatDim", NULL }, + { TIFFTAG_BLACKLEVEL, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "BlackLevel", NULL }, + { TIFFTAG_BLACKLEVELDELTAH, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "BlackLevelDeltaH", NULL }, + { TIFFTAG_BLACKLEVELDELTAV, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "BlackLevelDeltaV", NULL }, + { TIFFTAG_WHITELEVEL, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "WhiteLevel", NULL }, + { TIFFTAG_DEFAULTSCALE, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DefaultScale", NULL }, + { TIFFTAG_BESTQUALITYSCALE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BestQualityScale", NULL }, + { TIFFTAG_DEFAULTCROPORIGIN, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DefaultCropOrigin", NULL }, + { TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "DefaultCropSize", NULL }, + { TIFFTAG_COLORMATRIX1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ColorMatrix1", NULL }, + { TIFFTAG_COLORMATRIX2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ColorMatrix2", NULL }, + { TIFFTAG_CAMERACALIBRATION1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CameraCalibration1", NULL }, + { TIFFTAG_CAMERACALIBRATION2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CameraCalibration2", NULL }, + { TIFFTAG_REDUCTIONMATRIX1, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ReductionMatrix1", NULL }, + { TIFFTAG_REDUCTIONMATRIX2, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ReductionMatrix2", NULL }, + { TIFFTAG_ANALOGBALANCE, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "AnalogBalance", NULL }, + { TIFFTAG_ASSHOTNEUTRAL, -1, -1, TIFF_RATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "AsShotNeutral", NULL }, + { TIFFTAG_ASSHOTWHITEXY, 2, 2, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "AsShotWhiteXY", NULL }, + { TIFFTAG_BASELINEEXPOSURE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BaselineExposure", NULL }, + { TIFFTAG_BASELINENOISE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BaselineNoise", NULL }, + { TIFFTAG_BASELINESHARPNESS, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BaselineSharpness", NULL }, + { TIFFTAG_BAYERGREENSPLIT, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "BayerGreenSplit", NULL }, + { TIFFTAG_LINEARRESPONSELIMIT, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "LinearResponseLimit", NULL }, + { TIFFTAG_CAMERASERIALNUMBER, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CameraSerialNumber", NULL }, + { TIFFTAG_LENSINFO, 4, 4, TIFF_RATIONAL, 0, TIFF_SETGET_C0_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "LensInfo", NULL }, + { TIFFTAG_CHROMABLURRADIUS, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ChromaBlurRadius", NULL }, + { TIFFTAG_ANTIALIASSTRENGTH, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "AntiAliasStrength", NULL }, + { TIFFTAG_SHADOWSCALE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ShadowScale", NULL }, + { TIFFTAG_DNGPRIVATEDATA, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "DNGPrivateData", NULL }, + { TIFFTAG_MAKERNOTESAFETY, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "MakerNoteSafety", NULL }, + { TIFFTAG_CALIBRATIONILLUMINANT1, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CalibrationIlluminant1", NULL }, + { TIFFTAG_CALIBRATIONILLUMINANT2, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CalibrationIlluminant2", NULL }, + { TIFFTAG_RAWDATAUNIQUEID, 16, 16, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "RawDataUniqueID", NULL }, + { TIFFTAG_ORIGINALRAWFILENAME, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OriginalRawFileName", NULL }, + { TIFFTAG_ORIGINALRAWFILEDATA, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "OriginalRawFileData", NULL }, + { TIFFTAG_ACTIVEAREA, 4, 4, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ActiveArea", NULL }, + { TIFFTAG_MASKEDAREAS, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "MaskedAreas", NULL }, + { TIFFTAG_ASSHOTICCPROFILE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "AsShotICCProfile", NULL }, + { TIFFTAG_ASSHOTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "AsShotPreProfileMatrix", NULL }, + { TIFFTAG_CURRENTICCPROFILE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CurrentICCProfile", NULL }, + { TIFFTAG_CURRENTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "CurrentPreProfileMatrix", NULL }, + { TIFFTAG_PERSAMPLE, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "PerSample", NULL}, + /* end DNG tags */ + /* begin TIFF/FX tags */ + { TIFFTAG_INDEXED, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "Indexed", NULL }, + { TIFFTAG_GLOBALPARAMETERSIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "GlobalParametersIFD", NULL }, + { TIFFTAG_PROFILETYPE, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ProfileType", NULL }, + { TIFFTAG_FAXPROFILE, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "FaxProfile", NULL }, + { TIFFTAG_CODINGMETHODS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "CodingMethods", NULL }, + { TIFFTAG_VERSIONYEAR, 4, 4, TIFF_BYTE, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "VersionYear", NULL }, + { TIFFTAG_MODENUMBER, 1, 1, TIFF_BYTE, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ModeNumber", NULL }, + { TIFFTAG_DECODE, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "Decode", NULL }, + { TIFFTAG_IMAGEBASECOLOR, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "ImageBaseColor", NULL }, + { TIFFTAG_T82OPTIONS, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "T82Options", NULL }, + { TIFFTAG_STRIPROWCOUNTS, -1, -1, TIFF_LONG, 0, TIFF_SETGET_C16_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 1, "StripRowCounts", NULL }, + { TIFFTAG_IMAGELAYER, 2, 2, TIFF_LONG, 0, TIFF_SETGET_C0_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "ImageLayer", NULL }, + /* end TIFF/FX tags */ + /* begin pseudo tags */ }; -static TIFFField +static const TIFFField exifFields[] = { - { EXIFTAG_EXPOSURETIME, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureTime", NULL }, - { EXIFTAG_FNUMBER, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FNumber", NULL }, - { EXIFTAG_EXPOSUREPROGRAM, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureProgram", NULL }, - { EXIFTAG_SPECTRALSENSITIVITY, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SpectralSensitivity", NULL }, - { EXIFTAG_ISOSPEEDRATINGS, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ISOSpeedRatings", NULL }, - { EXIFTAG_OECF, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OptoelectricConversionFactor", NULL }, - { EXIFTAG_EXIFVERSION, 4, 4, TIFF_UNDEFINED, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExifVersion", NULL }, - { EXIFTAG_DATETIMEORIGINAL, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTimeOriginal", NULL }, - { EXIFTAG_DATETIMEDIGITIZED, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTimeDigitized", NULL }, - { EXIFTAG_COMPONENTSCONFIGURATION, 4, 4, TIFF_UNDEFINED, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ComponentsConfiguration", NULL }, - { EXIFTAG_COMPRESSEDBITSPERPIXEL, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CompressedBitsPerPixel", NULL }, - { EXIFTAG_SHUTTERSPEEDVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ShutterSpeedValue", NULL }, - { EXIFTAG_APERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ApertureValue", NULL }, - { EXIFTAG_BRIGHTNESSVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BrightnessValue", NULL }, - { EXIFTAG_EXPOSUREBIASVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureBiasValue", NULL }, - { EXIFTAG_MAXAPERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MaxApertureValue", NULL }, - { EXIFTAG_SUBJECTDISTANCE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectDistance", NULL }, - { EXIFTAG_METERINGMODE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MeteringMode", NULL }, - { EXIFTAG_LIGHTSOURCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LightSource", NULL }, - { EXIFTAG_FLASH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Flash", NULL }, - { EXIFTAG_FOCALLENGTH, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalLength", NULL }, - { EXIFTAG_SUBJECTAREA, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "SubjectArea", NULL }, - { EXIFTAG_MAKERNOTE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "MakerNote", NULL }, - { EXIFTAG_USERCOMMENT, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "UserComment", NULL }, - { EXIFTAG_SUBSECTIME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTime", NULL }, - { EXIFTAG_SUBSECTIMEORIGINAL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTimeOriginal", NULL }, - { EXIFTAG_SUBSECTIMEDIGITIZED, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTimeDigitized", NULL }, - { EXIFTAG_FLASHPIXVERSION, 4, 4, TIFF_UNDEFINED, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FlashpixVersion", NULL }, - { EXIFTAG_COLORSPACE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ColorSpace", NULL }, - { EXIFTAG_PIXELXDIMENSION, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PixelXDimension", NULL }, - { EXIFTAG_PIXELYDIMENSION, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PixelYDimension", NULL }, - { EXIFTAG_RELATEDSOUNDFILE, 13, 13, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "RelatedSoundFile", NULL }, - { EXIFTAG_FLASHENERGY, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FlashEnergy", NULL }, - { EXIFTAG_SPATIALFREQUENCYRESPONSE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "SpatialFrequencyResponse", NULL }, - { EXIFTAG_FOCALPLANEXRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneXResolution", NULL }, - { EXIFTAG_FOCALPLANEYRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneYResolution", NULL }, - { EXIFTAG_FOCALPLANERESOLUTIONUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneResolutionUnit", NULL }, - { EXIFTAG_SUBJECTLOCATION, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectLocation", NULL }, - { EXIFTAG_EXPOSUREINDEX, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureIndex", NULL }, - { EXIFTAG_SENSINGMETHOD, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SensingMethod", NULL }, - { EXIFTAG_FILESOURCE, 1, 1, TIFF_UNDEFINED, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FileSource", NULL }, - { EXIFTAG_SCENETYPE, 1, 1, TIFF_UNDEFINED, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SceneType", NULL }, - { EXIFTAG_CFAPATTERN, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CFAPattern", NULL }, - { EXIFTAG_CUSTOMRENDERED, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CustomRendered", NULL }, - { EXIFTAG_EXPOSUREMODE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureMode", NULL }, - { EXIFTAG_WHITEBALANCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WhiteBalance", NULL }, - { EXIFTAG_DIGITALZOOMRATIO, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DigitalZoomRatio", NULL }, - { EXIFTAG_FOCALLENGTHIN35MMFILM, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalLengthIn35mmFilm", NULL }, - { EXIFTAG_SCENECAPTURETYPE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SceneCaptureType", NULL }, - { EXIFTAG_GAINCONTROL, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "GainControl", NULL }, - { EXIFTAG_CONTRAST, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Contrast", NULL }, - { EXIFTAG_SATURATION, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Saturation", NULL }, - { EXIFTAG_SHARPNESS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Sharpness", NULL }, - { EXIFTAG_DEVICESETTINGDESCRIPTION, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "DeviceSettingDescription", NULL }, - { EXIFTAG_SUBJECTDISTANCERANGE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectDistanceRange", NULL }, - { EXIFTAG_IMAGEUNIQUEID, 33, 33, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageUniqueID", NULL } + { EXIFTAG_EXPOSURETIME, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureTime", NULL }, + { EXIFTAG_FNUMBER, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FNumber", NULL }, + { EXIFTAG_EXPOSUREPROGRAM, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureProgram", NULL }, + { EXIFTAG_SPECTRALSENSITIVITY, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SpectralSensitivity", NULL }, + { EXIFTAG_ISOSPEEDRATINGS, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "ISOSpeedRatings", NULL }, + { EXIFTAG_OECF, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "OptoelectricConversionFactor", NULL }, + { EXIFTAG_EXIFVERSION, 4, 4, TIFF_UNDEFINED, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExifVersion", NULL }, + { EXIFTAG_DATETIMEORIGINAL, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTimeOriginal", NULL }, + { EXIFTAG_DATETIMEDIGITIZED, 20, 20, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DateTimeDigitized", NULL }, + { EXIFTAG_COMPONENTSCONFIGURATION, 4, 4, TIFF_UNDEFINED, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ComponentsConfiguration", NULL }, + { EXIFTAG_COMPRESSEDBITSPERPIXEL, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CompressedBitsPerPixel", NULL }, + { EXIFTAG_SHUTTERSPEEDVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ShutterSpeedValue", NULL }, + { EXIFTAG_APERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ApertureValue", NULL }, + { EXIFTAG_BRIGHTNESSVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BrightnessValue", NULL }, + { EXIFTAG_EXPOSUREBIASVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureBiasValue", NULL }, + { EXIFTAG_MAXAPERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MaxApertureValue", NULL }, + { EXIFTAG_SUBJECTDISTANCE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectDistance", NULL }, + { EXIFTAG_METERINGMODE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MeteringMode", NULL }, + { EXIFTAG_LIGHTSOURCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "LightSource", NULL }, + { EXIFTAG_FLASH, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Flash", NULL }, + { EXIFTAG_FOCALLENGTH, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalLength", NULL }, + { EXIFTAG_SUBJECTAREA, -1, -1, TIFF_SHORT, 0, TIFF_SETGET_C16_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "SubjectArea", NULL }, + { EXIFTAG_MAKERNOTE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "MakerNote", NULL }, + { EXIFTAG_USERCOMMENT, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "UserComment", NULL }, + { EXIFTAG_SUBSECTIME, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTime", NULL }, + { EXIFTAG_SUBSECTIMEORIGINAL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTimeOriginal", NULL }, + { EXIFTAG_SUBSECTIMEDIGITIZED, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubSecTimeDigitized", NULL }, + { EXIFTAG_FLASHPIXVERSION, 4, 4, TIFF_UNDEFINED, 0, TIFF_SETGET_C0_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FlashpixVersion", NULL }, + { EXIFTAG_COLORSPACE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ColorSpace", NULL }, + { EXIFTAG_PIXELXDIMENSION, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PixelXDimension", NULL }, + { EXIFTAG_PIXELYDIMENSION, 1, 1, TIFF_LONG, 0, TIFF_SETGET_UINT32, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "PixelYDimension", NULL }, + { EXIFTAG_RELATEDSOUNDFILE, 13, 13, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "RelatedSoundFile", NULL }, + { EXIFTAG_FLASHENERGY, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FlashEnergy", NULL }, + { EXIFTAG_SPATIALFREQUENCYRESPONSE, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "SpatialFrequencyResponse", NULL }, + { EXIFTAG_FOCALPLANEXRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneXResolution", NULL }, + { EXIFTAG_FOCALPLANEYRESOLUTION, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneYResolution", NULL }, + { EXIFTAG_FOCALPLANERESOLUTIONUNIT, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalPlaneResolutionUnit", NULL }, + { EXIFTAG_SUBJECTLOCATION, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectLocation", NULL }, + { EXIFTAG_EXPOSUREINDEX, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureIndex", NULL }, + { EXIFTAG_SENSINGMETHOD, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SensingMethod", NULL }, + { EXIFTAG_FILESOURCE, 1, 1, TIFF_UNDEFINED, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FileSource", NULL }, + { EXIFTAG_SCENETYPE, 1, 1, TIFF_UNDEFINED, 0, TIFF_SETGET_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SceneType", NULL }, + { EXIFTAG_CFAPATTERN, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CFAPattern", NULL }, + { EXIFTAG_CUSTOMRENDERED, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "CustomRendered", NULL }, + { EXIFTAG_EXPOSUREMODE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureMode", NULL }, + { EXIFTAG_WHITEBALANCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "WhiteBalance", NULL }, + { EXIFTAG_DIGITALZOOMRATIO, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "DigitalZoomRatio", NULL }, + { EXIFTAG_FOCALLENGTHIN35MMFILM, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "FocalLengthIn35mmFilm", NULL }, + { EXIFTAG_SCENECAPTURETYPE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SceneCaptureType", NULL }, + { EXIFTAG_GAINCONTROL, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_DOUBLE, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "GainControl", NULL }, + { EXIFTAG_CONTRAST, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Contrast", NULL }, + { EXIFTAG_SATURATION, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Saturation", NULL }, + { EXIFTAG_SHARPNESS, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "Sharpness", NULL }, + { EXIFTAG_DEVICESETTINGDESCRIPTION, -1, -1, TIFF_UNDEFINED, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "DeviceSettingDescription", NULL }, + { EXIFTAG_SUBJECTDISTANCERANGE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectDistanceRange", NULL }, + { EXIFTAG_IMAGEUNIQUEID, 33, 33, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ImageUniqueID", NULL } }; -static TIFFFieldArray -tiffFieldArray = { tfiatImage, 0, TIFFArrayCount(tiffFields), tiffFields }; -static TIFFFieldArray -exifFieldArray = { tfiatExif, 0, TIFFArrayCount(exifFields), exifFields }; +static const TIFFFieldArray +tiffFieldArray = { tfiatImage, 0, TIFFArrayCount(tiffFields), (TIFFField*) tiffFields }; +static const TIFFFieldArray +exifFieldArray = { tfiatExif, 0, TIFFArrayCount(exifFields), (TIFFField*) exifFields }; /* - * We have our own local lfind() equivelent to avoid subtle differences - * in types passed to lfind() on different systems. + * We have our own local lfind() equivalent to avoid subtle differences + * in types passed to lfind() on different systems. */ static void * @@ -282,131 +306,131 @@ td_lfind(const void *key, const void *base, size_t *nmemb, size_t size, const TIFFFieldArray* _TIFFGetFields(void) { - return(&tiffFieldArray); + return(&tiffFieldArray); } const TIFFFieldArray* _TIFFGetExifFields(void) { - return(&exifFieldArray); + return(&exifFieldArray); } void _TIFFSetupFields(TIFF* tif, const TIFFFieldArray* fieldarray) { - if (tif->tif_fields && tif->tif_nfields > 0) { - uint32 i; + if (tif->tif_fields && tif->tif_nfields > 0) { + uint32 i; - for (i = 0; i < tif->tif_nfields; i++) { - TIFFField *fld = tif->tif_fields[i]; - if (fld->field_bit == FIELD_CUSTOM && - strncmp("Tag ", fld->field_name, 4) == 0) { - _TIFFfree(fld->field_name); - _TIFFfree(fld); - } - } + for (i = 0; i < tif->tif_nfields; i++) { + TIFFField *fld = tif->tif_fields[i]; + if (fld->field_bit == FIELD_CUSTOM && + strncmp("Tag ", fld->field_name, 4) == 0) { + _TIFFfree(fld->field_name); + _TIFFfree(fld); + } + } - _TIFFfree(tif->tif_fields); - tif->tif_fields = NULL; - tif->tif_nfields = 0; - } - if (!_TIFFMergeFields(tif, fieldarray->fields, fieldarray->count)) { - TIFFErrorExt(tif->tif_clientdata, "_TIFFSetupFields", - "Setting up field info failed"); - } + _TIFFfree(tif->tif_fields); + tif->tif_fields = NULL; + tif->tif_nfields = 0; + } + if (!_TIFFMergeFields(tif, fieldarray->fields, fieldarray->count)) { + TIFFErrorExt(tif->tif_clientdata, "_TIFFSetupFields", + "Setting up field info failed"); + } } static int tagCompare(const void* a, const void* b) { - const TIFFField* ta = *(const TIFFField**) a; - const TIFFField* tb = *(const TIFFField**) b; - /* NB: be careful of return values for 16-bit platforms */ - if (ta->field_tag != tb->field_tag) - return (int)ta->field_tag - (int)tb->field_tag; - else - return (ta->field_type == TIFF_ANY) ? - 0 : ((int)tb->field_type - (int)ta->field_type); + const TIFFField* ta = *(const TIFFField**) a; + const TIFFField* tb = *(const TIFFField**) b; + /* NB: be careful of return values for 16-bit platforms */ + if (ta->field_tag != tb->field_tag) + return (int)ta->field_tag - (int)tb->field_tag; + else + return (ta->field_type == TIFF_ANY) ? + 0 : ((int)tb->field_type - (int)ta->field_type); } static int tagNameCompare(const void* a, const void* b) { - const TIFFField* ta = *(const TIFFField**) a; - const TIFFField* tb = *(const TIFFField**) b; - int ret = strcmp(ta->field_name, tb->field_name); + const TIFFField* ta = *(const TIFFField**) a; + const TIFFField* tb = *(const TIFFField**) b; + int ret = strcmp(ta->field_name, tb->field_name); - if (ret) - return ret; - else - return (ta->field_type == TIFF_ANY) ? - 0 : ((int)tb->field_type - (int)ta->field_type); + if (ret) + return ret; + else + return (ta->field_type == TIFF_ANY) ? + 0 : ((int)tb->field_type - (int)ta->field_type); } int _TIFFMergeFields(TIFF* tif, const TIFFField info[], uint32 n) { - static const char module[] = "_TIFFMergeFields"; - static const char reason[] = "for fields array"; - TIFFField** tp; - uint32 i; + static const char module[] = "_TIFFMergeFields"; + static const char reason[] = "for fields array"; + /* TIFFField** tp; */ + uint32 i; tif->tif_foundfield = NULL; - if (tif->tif_fields && tif->tif_nfields > 0) { - tif->tif_fields = (TIFFField**) - _TIFFCheckRealloc(tif, tif->tif_fields, - (tif->tif_nfields + n), - sizeof(TIFFField *), reason); - } else { - tif->tif_fields = (TIFFField **) - _TIFFCheckMalloc(tif, n, sizeof(TIFFField *), - reason); - } - if (!tif->tif_fields) { - TIFFErrorExt(tif->tif_clientdata, module, - "Failed to allocate fields array"); - return 0; - } + if (tif->tif_fields && tif->tif_nfields > 0) { + tif->tif_fields = (TIFFField**) + _TIFFCheckRealloc(tif, tif->tif_fields, + (tif->tif_nfields + n), + sizeof(TIFFField *), reason); + } else { + tif->tif_fields = (TIFFField **) + _TIFFCheckMalloc(tif, n, sizeof(TIFFField *), + reason); + } + if (!tif->tif_fields) { + TIFFErrorExt(tif->tif_clientdata, module, + "Failed to allocate fields array"); + return 0; + } - tp = tif->tif_fields + tif->tif_nfields; - for (i = 0; i < n; i++) { - const TIFFField *fip = - TIFFFindField(tif, info[i].field_tag, TIFF_ANY); + /* tp = tif->tif_fields + tif->tif_nfields; */ + for (i = 0; i < n; i++) { + const TIFFField *fip = + TIFFFindField(tif, info[i].field_tag, TIFF_ANY); /* only add definitions that aren't already present */ - if (!fip) { + if (!fip) { tif->tif_fields[tif->tif_nfields] = (TIFFField *) (info+i); tif->tif_nfields++; } - } + } /* Sort the field info by tag number */ - qsort(tif->tif_fields, tif->tif_nfields, - sizeof(TIFFField *), tagCompare); + qsort(tif->tif_fields, tif->tif_nfields, + sizeof(TIFFField *), tagCompare); - return n; + return n; } void _TIFFPrintFieldInfo(TIFF* tif, FILE* fd) { - uint32 i; + uint32 i; - fprintf(fd, "%s: \n", tif->tif_name); - for (i = 0; i < tif->tif_nfields; i++) { - const TIFFField* fip = tif->tif_fields[i]; - fprintf(fd, "field[%2d] %5lu, %2d, %2d, %d, %2d, %5s, %5s, %s\n" - , (int)i - , (unsigned long) fip->field_tag - , fip->field_readcount, fip->field_writecount - , fip->field_type - , fip->field_bit - , fip->field_oktochange ? "TRUE" : "FALSE" - , fip->field_passcount ? "TRUE" : "FALSE" - , fip->field_name - ); - } + fprintf(fd, "%s: \n", tif->tif_name); + for (i = 0; i < tif->tif_nfields; i++) { + const TIFFField* fip = tif->tif_fields[i]; + fprintf(fd, "field[%2d] %5lu, %2d, %2d, %d, %2d, %5s, %5s, %s\n" + , (int)i + , (unsigned long) fip->field_tag + , fip->field_readcount, fip->field_writecount + , fip->field_type + , fip->field_bit + , fip->field_oktochange ? "TRUE" : "FALSE" + , fip->field_passcount ? "TRUE" : "FALSE" + , fip->field_name + ); + } } /* @@ -415,32 +439,32 @@ _TIFFPrintFieldInfo(TIFF* tif, FILE* fd) int TIFFDataWidth(TIFFDataType type) { - switch(type) - { - case 0: /* nothing */ - case TIFF_BYTE: - case TIFF_ASCII: - case TIFF_SBYTE: - case TIFF_UNDEFINED: - return 1; - case TIFF_SHORT: - case TIFF_SSHORT: - return 2; - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_FLOAT: - case TIFF_IFD: - return 4; - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - case TIFF_DOUBLE: - case TIFF_LONG8: - case TIFF_SLONG8: - case TIFF_IFD8: - return 8; - default: - return 0; /* will return 0 for unknown types */ - } + switch(type) + { + case 0: /* nothing */ + case TIFF_BYTE: + case TIFF_ASCII: + case TIFF_SBYTE: + case TIFF_UNDEFINED: + return 1; + case TIFF_SHORT: + case TIFF_SSHORT: + return 2; + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_FLOAT: + case TIFF_IFD: + return 4; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_DOUBLE: + case TIFF_LONG8: + case TIFF_SLONG8: + case TIFF_IFD8: + return 8; + default: + return 0; /* will return 0 for unknown types */ + } } /* @@ -453,217 +477,253 @@ TIFFDataWidth(TIFFDataType type) int _TIFFDataSize(TIFFDataType type) { - switch (type) - { - case TIFF_BYTE: - case TIFF_SBYTE: - case TIFF_ASCII: - case TIFF_UNDEFINED: - return 1; - case TIFF_SHORT: - case TIFF_SSHORT: - return 2; - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_FLOAT: - case TIFF_IFD: - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - return 4; - case TIFF_DOUBLE: - case TIFF_LONG8: - case TIFF_SLONG8: - case TIFF_IFD8: - return 8; - default: - return 0; - } + switch (type) + { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_ASCII: + case TIFF_UNDEFINED: + return 1; + case TIFF_SHORT: + case TIFF_SSHORT: + return 2; + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_FLOAT: + case TIFF_IFD: + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + return 4; + case TIFF_DOUBLE: + case TIFF_LONG8: + case TIFF_SLONG8: + case TIFF_IFD8: + return 8; + default: + return 0; + } } const TIFFField* TIFFFindField(TIFF* tif, uint32 tag, TIFFDataType dt) { - TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, 0, NULL, NULL}; - TIFFField* pkey = &key; - const TIFFField **ret; - if (tif->tif_foundfield && tif->tif_foundfield->field_tag == tag && - (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type)) - return tif->tif_foundfield; + TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, 0, NULL, NULL}; + TIFFField* pkey = &key; + const TIFFField **ret; + if (tif->tif_foundfield && tif->tif_foundfield->field_tag == tag && + (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type)) + return tif->tif_foundfield; - /* If we are invoked with no field information, then just return. */ - if (!tif->tif_fields) - return NULL; + /* If we are invoked with no field information, then just return. */ + if (!tif->tif_fields) + return NULL; - /* NB: use sorted search (e.g. binary search) */ + /* NB: use sorted search (e.g. binary search) */ - key.field_tag = tag; - key.field_type = dt; + key.field_tag = tag; + key.field_type = dt; - ret = (const TIFFField **) bsearch(&pkey, tif->tif_fields, - tif->tif_nfields, - sizeof(TIFFField *), tagCompare); - return tif->tif_foundfield = (ret ? *ret : NULL); + ret = (const TIFFField **) bsearch(&pkey, tif->tif_fields, + tif->tif_nfields, + sizeof(TIFFField *), tagCompare); + return tif->tif_foundfield = (ret ? *ret : NULL); } -const TIFFField* +static const TIFFField* _TIFFFindFieldByName(TIFF* tif, const char *field_name, TIFFDataType dt) { - TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, 0, NULL, NULL}; - TIFFField* pkey = &key; - const TIFFField **ret; - if (tif->tif_foundfield - && streq(tif->tif_foundfield->field_name, field_name) - && (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type)) - return (tif->tif_foundfield); + TIFFField key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0, 0, 0, NULL, NULL}; + TIFFField* pkey = &key; + const TIFFField **ret; + if (tif->tif_foundfield + && streq(tif->tif_foundfield->field_name, field_name) + && (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type)) + return (tif->tif_foundfield); - /* If we are invoked with no field information, then just return. */ - if (!tif->tif_fields) - return NULL; + /* If we are invoked with no field information, then just return. */ + if (!tif->tif_fields) + return NULL; - /* NB: use linear search since list is sorted by key#, not name */ + /* NB: use linear search since list is sorted by key#, not name */ - key.field_name = (char *)field_name; - key.field_type = dt; + key.field_name = (char *)field_name; + key.field_type = dt; - ret = (const TIFFField **) + ret = (const TIFFField **) td_lfind(&pkey, tif->tif_fields, &tif->tif_nfields, sizeof(TIFFField *), tagNameCompare); - return tif->tif_foundfield = (ret ? *ret : NULL); + return tif->tif_foundfield = (ret ? *ret : NULL); } const TIFFField* TIFFFieldWithTag(TIFF* tif, uint32 tag) { - const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY); - if (!fip) { - TIFFErrorExt(tif->tif_clientdata, "TIFFFieldWithTag", - "Internal error, unknown tag 0x%x", - (unsigned int) tag); - } - return (fip); + const TIFFField* fip = TIFFFindField(tif, tag, TIFF_ANY); + if (!fip) { + TIFFErrorExt(tif->tif_clientdata, "TIFFFieldWithTag", + "Internal error, unknown tag 0x%x", + (unsigned int) tag); + } + return (fip); } const TIFFField* TIFFFieldWithName(TIFF* tif, const char *field_name) { - const TIFFField* fip = - _TIFFFindFieldByName(tif, field_name, TIFF_ANY); - if (!fip) { - TIFFErrorExt(tif->tif_clientdata, "TIFFFieldWithName", - "Internal error, unknown tag %s", field_name); - } - return (fip); + const TIFFField* fip = + _TIFFFindFieldByName(tif, field_name, TIFF_ANY); + if (!fip) { + TIFFErrorExt(tif->tif_clientdata, "TIFFFieldWithName", + "Internal error, unknown tag %s", field_name); + } + return (fip); +} + +uint32 +TIFFFieldTag(const TIFFField* fip) +{ + return fip->field_tag; +} + +const char * +TIFFFieldName(const TIFFField* fip) +{ + return fip->field_name; +} + +TIFFDataType +TIFFFieldDataType(const TIFFField* fip) +{ + return fip->field_type; +} + +int +TIFFFieldPassCount(const TIFFField* fip) +{ + return fip->field_passcount; +} + +int +TIFFFieldReadCount(const TIFFField* fip) +{ + return fip->field_readcount; +} + +int +TIFFFieldWriteCount(const TIFFField* fip) +{ + return fip->field_writecount; } const TIFFField* _TIFFFindOrRegisterField(TIFF *tif, uint32 tag, TIFFDataType dt) { - const TIFFField *fld; + const TIFFField *fld; - fld = TIFFFindField(tif, tag, dt); - if (fld == NULL) { - fld = _TIFFCreateAnonField(tif, tag, dt); - if (!_TIFFMergeFields(tif, fld, 1)) - return NULL; - } + fld = TIFFFindField(tif, tag, dt); + if (fld == NULL) { + fld = _TIFFCreateAnonField(tif, tag, dt); + if (!_TIFFMergeFields(tif, fld, 1)) + return NULL; + } - return fld; + return fld; } TIFFField* _TIFFCreateAnonField(TIFF *tif, uint32 tag, TIFFDataType field_type) { - TIFFField *fld; - (void) tif; + TIFFField *fld; + (void) tif; - fld = (TIFFField *) _TIFFmalloc(sizeof (TIFFField)); - if (fld == NULL) - return NULL; - _TIFFmemset(fld, 0, sizeof(TIFFField)); + fld = (TIFFField *) _TIFFmalloc(sizeof (TIFFField)); + if (fld == NULL) + return NULL; + _TIFFmemset(fld, 0, sizeof(TIFFField)); - fld->field_tag = tag; - fld->field_readcount = TIFF_VARIABLE2; - fld->field_writecount = TIFF_VARIABLE2; - fld->field_type = field_type; - fld->reserved = 0; - switch (field_type) - { - case TIFF_BYTE: - case TIFF_UNDEFINED: - fld->set_field_type = TIFF_SETGET_C32_UINT8; - fld->get_field_type = TIFF_SETGET_C32_UINT8; - break; - case TIFF_ASCII: - fld->set_field_type = TIFF_SETGET_C32_ASCII; - fld->get_field_type = TIFF_SETGET_C32_ASCII; - break; - case TIFF_SHORT: - fld->set_field_type = TIFF_SETGET_C32_UINT16; - fld->get_field_type = TIFF_SETGET_C32_UINT16; - break; - case TIFF_LONG: - fld->set_field_type = TIFF_SETGET_C32_UINT32; - fld->get_field_type = TIFF_SETGET_C32_UINT32; - break; - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - case TIFF_FLOAT: - fld->set_field_type = TIFF_SETGET_C32_FLOAT; - fld->get_field_type = TIFF_SETGET_C32_FLOAT; - break; - case TIFF_SBYTE: - fld->set_field_type = TIFF_SETGET_C32_SINT8; - fld->get_field_type = TIFF_SETGET_C32_SINT8; - break; - case TIFF_SSHORT: - fld->set_field_type = TIFF_SETGET_C32_SINT16; - fld->get_field_type = TIFF_SETGET_C32_SINT16; - break; - case TIFF_SLONG: - fld->set_field_type = TIFF_SETGET_C32_SINT32; - fld->get_field_type = TIFF_SETGET_C32_SINT32; - break; - case TIFF_DOUBLE: - fld->set_field_type = TIFF_SETGET_C32_DOUBLE; - fld->get_field_type = TIFF_SETGET_C32_DOUBLE; - break; - case TIFF_IFD: - case TIFF_IFD8: - fld->set_field_type = TIFF_SETGET_C32_IFD8; - fld->get_field_type = TIFF_SETGET_C32_IFD8; - break; - case TIFF_LONG8: - fld->set_field_type = TIFF_SETGET_C32_UINT64; - fld->get_field_type = TIFF_SETGET_C32_UINT64; - break; - case TIFF_SLONG8: - fld->set_field_type = TIFF_SETGET_C32_SINT64; - fld->get_field_type = TIFF_SETGET_C32_SINT64; - break; - default: - fld->set_field_type = TIFF_SETGET_UNDEFINED; - fld->get_field_type = TIFF_SETGET_UNDEFINED; - break; - } - fld->field_bit = FIELD_CUSTOM; - fld->field_oktochange = TRUE; - fld->field_passcount = TRUE; - fld->field_name = (char *) _TIFFmalloc(32); - if (fld->field_name == NULL) { - _TIFFfree(fld); - return NULL; - } - fld->field_subfields = NULL; + fld->field_tag = tag; + fld->field_readcount = TIFF_VARIABLE2; + fld->field_writecount = TIFF_VARIABLE2; + fld->field_type = field_type; + fld->reserved = 0; + switch (field_type) + { + case TIFF_BYTE: + case TIFF_UNDEFINED: + fld->set_field_type = TIFF_SETGET_C32_UINT8; + fld->get_field_type = TIFF_SETGET_C32_UINT8; + break; + case TIFF_ASCII: + fld->set_field_type = TIFF_SETGET_C32_ASCII; + fld->get_field_type = TIFF_SETGET_C32_ASCII; + break; + case TIFF_SHORT: + fld->set_field_type = TIFF_SETGET_C32_UINT16; + fld->get_field_type = TIFF_SETGET_C32_UINT16; + break; + case TIFF_LONG: + fld->set_field_type = TIFF_SETGET_C32_UINT32; + fld->get_field_type = TIFF_SETGET_C32_UINT32; + break; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + fld->set_field_type = TIFF_SETGET_C32_FLOAT; + fld->get_field_type = TIFF_SETGET_C32_FLOAT; + break; + case TIFF_SBYTE: + fld->set_field_type = TIFF_SETGET_C32_SINT8; + fld->get_field_type = TIFF_SETGET_C32_SINT8; + break; + case TIFF_SSHORT: + fld->set_field_type = TIFF_SETGET_C32_SINT16; + fld->get_field_type = TIFF_SETGET_C32_SINT16; + break; + case TIFF_SLONG: + fld->set_field_type = TIFF_SETGET_C32_SINT32; + fld->get_field_type = TIFF_SETGET_C32_SINT32; + break; + case TIFF_DOUBLE: + fld->set_field_type = TIFF_SETGET_C32_DOUBLE; + fld->get_field_type = TIFF_SETGET_C32_DOUBLE; + break; + case TIFF_IFD: + case TIFF_IFD8: + fld->set_field_type = TIFF_SETGET_C32_IFD8; + fld->get_field_type = TIFF_SETGET_C32_IFD8; + break; + case TIFF_LONG8: + fld->set_field_type = TIFF_SETGET_C32_UINT64; + fld->get_field_type = TIFF_SETGET_C32_UINT64; + break; + case TIFF_SLONG8: + fld->set_field_type = TIFF_SETGET_C32_SINT64; + fld->get_field_type = TIFF_SETGET_C32_SINT64; + break; + default: + fld->set_field_type = TIFF_SETGET_UNDEFINED; + fld->get_field_type = TIFF_SETGET_UNDEFINED; + break; + } + fld->field_bit = FIELD_CUSTOM; + fld->field_oktochange = TRUE; + fld->field_passcount = TRUE; + fld->field_name = (char *) _TIFFmalloc(32); + if (fld->field_name == NULL) { + _TIFFfree(fld); + return NULL; + } + fld->field_subfields = NULL; - /* - * note that this name is a special sign to TIFFClose() and - * _TIFFSetupFields() to free the field - */ - sprintf(fld->field_name, "Tag %d", (int) tag); + /* + * note that this name is a special sign to TIFFClose() and + * _TIFFSetupFields() to free the field + */ + (void) snprintf(fld->field_name, 32, "Tag %d", (int) tag); - return fld; + return fld; } /**************************************************************************** @@ -676,224 +736,327 @@ _TIFFCreateAnonField(TIFF *tif, uint32 tag, TIFFDataType field_type) static TIFFSetGetFieldType _TIFFSetGetType(TIFFDataType type, short count, unsigned char passcount) { - if (type == TIFF_ASCII && count == TIFF_VARIABLE && passcount == 0) - return TIFF_SETGET_ASCII; + if (type == TIFF_ASCII && count == TIFF_VARIABLE && passcount == 0) + return TIFF_SETGET_ASCII; - else if (count == 1 && passcount == 0) { - switch (type) - { - case TIFF_BYTE: - case TIFF_UNDEFINED: - return TIFF_SETGET_UINT8; - case TIFF_ASCII: - return TIFF_SETGET_ASCII; - case TIFF_SHORT: - return TIFF_SETGET_UINT16; - case TIFF_LONG: - return TIFF_SETGET_UINT32; - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - case TIFF_FLOAT: - return TIFF_SETGET_FLOAT; - case TIFF_SBYTE: - return TIFF_SETGET_SINT8; - case TIFF_SSHORT: - return TIFF_SETGET_SINT16; - case TIFF_SLONG: - return TIFF_SETGET_SINT32; - case TIFF_DOUBLE: - return TIFF_SETGET_DOUBLE; - case TIFF_IFD: - case TIFF_IFD8: - return TIFF_SETGET_IFD8; - case TIFF_LONG8: - return TIFF_SETGET_UINT64; - case TIFF_SLONG8: - return TIFF_SETGET_SINT64; - default: - return TIFF_SETGET_UNDEFINED; - } - } + else if (count == 1 && passcount == 0) { + switch (type) + { + case TIFF_BYTE: + case TIFF_UNDEFINED: + return TIFF_SETGET_UINT8; + case TIFF_ASCII: + return TIFF_SETGET_ASCII; + case TIFF_SHORT: + return TIFF_SETGET_UINT16; + case TIFF_LONG: + return TIFF_SETGET_UINT32; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + return TIFF_SETGET_FLOAT; + case TIFF_SBYTE: + return TIFF_SETGET_SINT8; + case TIFF_SSHORT: + return TIFF_SETGET_SINT16; + case TIFF_SLONG: + return TIFF_SETGET_SINT32; + case TIFF_DOUBLE: + return TIFF_SETGET_DOUBLE; + case TIFF_IFD: + case TIFF_IFD8: + return TIFF_SETGET_IFD8; + case TIFF_LONG8: + return TIFF_SETGET_UINT64; + case TIFF_SLONG8: + return TIFF_SETGET_SINT64; + default: + return TIFF_SETGET_UNDEFINED; + } + } - else if (count >= 1 && passcount == 0) { - switch (type) - { - case TIFF_BYTE: - case TIFF_UNDEFINED: - return TIFF_SETGET_C0_UINT8; - case TIFF_ASCII: - return TIFF_SETGET_C0_ASCII; - case TIFF_SHORT: - return TIFF_SETGET_C0_UINT16; - case TIFF_LONG: - return TIFF_SETGET_C0_UINT32; - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - case TIFF_FLOAT: - return TIFF_SETGET_C0_FLOAT; - case TIFF_SBYTE: - return TIFF_SETGET_C0_SINT8; - case TIFF_SSHORT: - return TIFF_SETGET_C0_SINT16; - case TIFF_SLONG: - return TIFF_SETGET_C0_SINT32; - case TIFF_DOUBLE: - return TIFF_SETGET_C0_DOUBLE; - case TIFF_IFD: - case TIFF_IFD8: - return TIFF_SETGET_C0_IFD8; - case TIFF_LONG8: - return TIFF_SETGET_C0_UINT64; - case TIFF_SLONG8: - return TIFF_SETGET_C0_SINT64; - default: - return TIFF_SETGET_UNDEFINED; - } - } + else if (count >= 1 && passcount == 0) { + switch (type) + { + case TIFF_BYTE: + case TIFF_UNDEFINED: + return TIFF_SETGET_C0_UINT8; + case TIFF_ASCII: + return TIFF_SETGET_C0_ASCII; + case TIFF_SHORT: + return TIFF_SETGET_C0_UINT16; + case TIFF_LONG: + return TIFF_SETGET_C0_UINT32; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + return TIFF_SETGET_C0_FLOAT; + case TIFF_SBYTE: + return TIFF_SETGET_C0_SINT8; + case TIFF_SSHORT: + return TIFF_SETGET_C0_SINT16; + case TIFF_SLONG: + return TIFF_SETGET_C0_SINT32; + case TIFF_DOUBLE: + return TIFF_SETGET_C0_DOUBLE; + case TIFF_IFD: + case TIFF_IFD8: + return TIFF_SETGET_C0_IFD8; + case TIFF_LONG8: + return TIFF_SETGET_C0_UINT64; + case TIFF_SLONG8: + return TIFF_SETGET_C0_SINT64; + default: + return TIFF_SETGET_UNDEFINED; + } + } - else if (count == TIFF_VARIABLE && passcount == 1) { - switch (type) - { - case TIFF_BYTE: - case TIFF_UNDEFINED: - return TIFF_SETGET_C16_UINT8; - case TIFF_ASCII: - return TIFF_SETGET_C16_ASCII; - case TIFF_SHORT: - return TIFF_SETGET_C16_UINT16; - case TIFF_LONG: - return TIFF_SETGET_C16_UINT32; - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - case TIFF_FLOAT: - return TIFF_SETGET_C16_FLOAT; - case TIFF_SBYTE: - return TIFF_SETGET_C16_SINT8; - case TIFF_SSHORT: - return TIFF_SETGET_C16_SINT16; - case TIFF_SLONG: - return TIFF_SETGET_C16_SINT32; - case TIFF_DOUBLE: - return TIFF_SETGET_C16_DOUBLE; - case TIFF_IFD: - case TIFF_IFD8: - return TIFF_SETGET_C16_IFD8; - case TIFF_LONG8: - return TIFF_SETGET_C16_UINT64; - case TIFF_SLONG8: - return TIFF_SETGET_C16_SINT64; - default: - return TIFF_SETGET_UNDEFINED; - } - } + else if (count == TIFF_VARIABLE && passcount == 1) { + switch (type) + { + case TIFF_BYTE: + case TIFF_UNDEFINED: + return TIFF_SETGET_C16_UINT8; + case TIFF_ASCII: + return TIFF_SETGET_C16_ASCII; + case TIFF_SHORT: + return TIFF_SETGET_C16_UINT16; + case TIFF_LONG: + return TIFF_SETGET_C16_UINT32; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + return TIFF_SETGET_C16_FLOAT; + case TIFF_SBYTE: + return TIFF_SETGET_C16_SINT8; + case TIFF_SSHORT: + return TIFF_SETGET_C16_SINT16; + case TIFF_SLONG: + return TIFF_SETGET_C16_SINT32; + case TIFF_DOUBLE: + return TIFF_SETGET_C16_DOUBLE; + case TIFF_IFD: + case TIFF_IFD8: + return TIFF_SETGET_C16_IFD8; + case TIFF_LONG8: + return TIFF_SETGET_C16_UINT64; + case TIFF_SLONG8: + return TIFF_SETGET_C16_SINT64; + default: + return TIFF_SETGET_UNDEFINED; + } + } - else if (count == TIFF_VARIABLE2 && passcount == 1) { - switch (type) - { - case TIFF_BYTE: - case TIFF_UNDEFINED: - return TIFF_SETGET_C32_UINT8; - case TIFF_ASCII: - return TIFF_SETGET_C32_ASCII; - case TIFF_SHORT: - return TIFF_SETGET_C32_UINT16; - case TIFF_LONG: - return TIFF_SETGET_C32_UINT32; - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - case TIFF_FLOAT: - return TIFF_SETGET_C32_FLOAT; - case TIFF_SBYTE: - return TIFF_SETGET_C32_SINT8; - case TIFF_SSHORT: - return TIFF_SETGET_C32_SINT16; - case TIFF_SLONG: - return TIFF_SETGET_C32_SINT32; - case TIFF_DOUBLE: - return TIFF_SETGET_C32_DOUBLE; - case TIFF_IFD: - case TIFF_IFD8: - return TIFF_SETGET_C32_IFD8; - case TIFF_LONG8: - return TIFF_SETGET_C32_UINT64; - case TIFF_SLONG8: - return TIFF_SETGET_C32_SINT64; - default: - return TIFF_SETGET_UNDEFINED; - } - } + else if (count == TIFF_VARIABLE2 && passcount == 1) { + switch (type) + { + case TIFF_BYTE: + case TIFF_UNDEFINED: + return TIFF_SETGET_C32_UINT8; + case TIFF_ASCII: + return TIFF_SETGET_C32_ASCII; + case TIFF_SHORT: + return TIFF_SETGET_C32_UINT16; + case TIFF_LONG: + return TIFF_SETGET_C32_UINT32; + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + return TIFF_SETGET_C32_FLOAT; + case TIFF_SBYTE: + return TIFF_SETGET_C32_SINT8; + case TIFF_SSHORT: + return TIFF_SETGET_C32_SINT16; + case TIFF_SLONG: + return TIFF_SETGET_C32_SINT32; + case TIFF_DOUBLE: + return TIFF_SETGET_C32_DOUBLE; + case TIFF_IFD: + case TIFF_IFD8: + return TIFF_SETGET_C32_IFD8; + case TIFF_LONG8: + return TIFF_SETGET_C32_UINT64; + case TIFF_SLONG8: + return TIFF_SETGET_C32_SINT64; + default: + return TIFF_SETGET_UNDEFINED; + } + } - return TIFF_SETGET_UNDEFINED; + return TIFF_SETGET_UNDEFINED; } int TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], uint32 n) { - static const char module[] = "TIFFMergeFieldInfo"; - static const char reason[] = "for fields array"; - TIFFField *tp; - size_t nfields; - uint32 i; + static const char module[] = "TIFFMergeFieldInfo"; + static const char reason[] = "for fields array"; + TIFFField *tp; + size_t nfields; + uint32 i; - if (tif->tif_nfieldscompat > 0) { - tif->tif_fieldscompat = (TIFFFieldArray *) - _TIFFCheckRealloc(tif, tif->tif_fieldscompat, - tif->tif_nfieldscompat + 1, - sizeof(TIFFFieldArray), reason); - } else { - tif->tif_fieldscompat = (TIFFFieldArray *) - _TIFFCheckMalloc(tif, 1, sizeof(TIFFFieldArray), - reason); - } - if (!tif->tif_fieldscompat) { - TIFFErrorExt(tif->tif_clientdata, module, - "Failed to allocate fields array"); - return -1; - } - nfields = tif->tif_nfieldscompat++; + if (tif->tif_nfieldscompat > 0) { + tif->tif_fieldscompat = (TIFFFieldArray *) + _TIFFCheckRealloc(tif, tif->tif_fieldscompat, + tif->tif_nfieldscompat + 1, + sizeof(TIFFFieldArray), reason); + } else { + tif->tif_fieldscompat = (TIFFFieldArray *) + _TIFFCheckMalloc(tif, 1, sizeof(TIFFFieldArray), + reason); + } + if (!tif->tif_fieldscompat) { + TIFFErrorExt(tif->tif_clientdata, module, + "Failed to allocate fields array"); + return -1; + } + nfields = tif->tif_nfieldscompat++; - tif->tif_fieldscompat[nfields].type = tfiatOther; - tif->tif_fieldscompat[nfields].allocated_size = n; - tif->tif_fieldscompat[nfields].count = n; - tif->tif_fieldscompat[nfields].fields = - (TIFFField *)_TIFFCheckMalloc(tif, n, sizeof(TIFFField), - reason); - if (!tif->tif_fieldscompat[nfields].fields) { - TIFFErrorExt(tif->tif_clientdata, module, - "Failed to allocate fields array"); - return -1; - } + tif->tif_fieldscompat[nfields].type = tfiatOther; + tif->tif_fieldscompat[nfields].allocated_size = n; + tif->tif_fieldscompat[nfields].count = n; + tif->tif_fieldscompat[nfields].fields = + (TIFFField *)_TIFFCheckMalloc(tif, n, sizeof(TIFFField), + reason); + if (!tif->tif_fieldscompat[nfields].fields) { + TIFFErrorExt(tif->tif_clientdata, module, + "Failed to allocate fields array"); + return -1; + } - tp = tif->tif_fieldscompat[nfields].fields; - for (i = 0; i < n; i++) { - tp->field_tag = info[i].field_tag; - tp->field_readcount = info[i].field_readcount; - tp->field_writecount = info[i].field_writecount; - tp->field_type = info[i].field_type; - tp->reserved = 0; - tp->set_field_type = - _TIFFSetGetType(info[i].field_type, - info[i].field_readcount, - info[i].field_passcount); - tp->get_field_type = - _TIFFSetGetType(info[i].field_type, - info[i].field_readcount, - info[i].field_passcount); - tp->field_bit = info[i].field_bit; - tp->field_oktochange = info[i].field_oktochange; - tp->field_passcount = info[i].field_passcount; - tp->field_name = info[i].field_name; - tp->field_subfields = NULL; - tp++; - } + tp = tif->tif_fieldscompat[nfields].fields; + for (i = 0; i < n; i++) { + tp->field_tag = info[i].field_tag; + tp->field_readcount = info[i].field_readcount; + tp->field_writecount = info[i].field_writecount; + tp->field_type = info[i].field_type; + tp->reserved = 0; + tp->set_field_type = + _TIFFSetGetType(info[i].field_type, + info[i].field_readcount, + info[i].field_passcount); + tp->get_field_type = + _TIFFSetGetType(info[i].field_type, + info[i].field_readcount, + info[i].field_passcount); + tp->field_bit = info[i].field_bit; + tp->field_oktochange = info[i].field_oktochange; + tp->field_passcount = info[i].field_passcount; + tp->field_name = info[i].field_name; + tp->field_subfields = NULL; + tp++; + } - if (!_TIFFMergeFields(tif, tif->tif_fieldscompat[nfields].fields, n)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Setting up field info failed"); - return -1; - } + if (!_TIFFMergeFields(tif, tif->tif_fieldscompat[nfields].fields, n)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Setting up field info failed"); + return -1; + } - return 0; + return 0; +} + +int +_TIFFCheckFieldIsValidForCodec(TIFF *tif, ttag_t tag) +{ + /* Filter out non-codec specific tags */ + switch (tag) { + /* Shared tags */ + case TIFFTAG_PREDICTOR: + /* JPEG tags */ + case TIFFTAG_JPEGTABLES: + /* OJPEG tags */ + case TIFFTAG_JPEGIFOFFSET: + case TIFFTAG_JPEGIFBYTECOUNT: + case TIFFTAG_JPEGQTABLES: + case TIFFTAG_JPEGDCTABLES: + case TIFFTAG_JPEGACTABLES: + case TIFFTAG_JPEGPROC: + case TIFFTAG_JPEGRESTARTINTERVAL: + /* CCITT* */ + case TIFFTAG_BADFAXLINES: + case TIFFTAG_CLEANFAXDATA: + case TIFFTAG_CONSECUTIVEBADFAXLINES: + case TIFFTAG_GROUP3OPTIONS: + case TIFFTAG_GROUP4OPTIONS: + break; + default: + return 1; + } + /* Check if codec specific tags are allowed for the current + * compression scheme (codec) */ + switch (tif->tif_dir.td_compression) { + case COMPRESSION_LZW: + if (tag == TIFFTAG_PREDICTOR) + return 1; + break; + case COMPRESSION_PACKBITS: + /* No codec-specific tags */ + break; + case COMPRESSION_THUNDERSCAN: + /* No codec-specific tags */ + break; + case COMPRESSION_NEXT: + /* No codec-specific tags */ + break; + case COMPRESSION_JPEG: + if (tag == TIFFTAG_JPEGTABLES) + return 1; + break; + case COMPRESSION_OJPEG: + switch (tag) { + case TIFFTAG_JPEGIFOFFSET: + case TIFFTAG_JPEGIFBYTECOUNT: + case TIFFTAG_JPEGQTABLES: + case TIFFTAG_JPEGDCTABLES: + case TIFFTAG_JPEGACTABLES: + case TIFFTAG_JPEGPROC: + case TIFFTAG_JPEGRESTARTINTERVAL: + return 1; + } + break; + case COMPRESSION_CCITTRLE: + case COMPRESSION_CCITTRLEW: + case COMPRESSION_CCITTFAX3: + case COMPRESSION_CCITTFAX4: + switch (tag) { + case TIFFTAG_BADFAXLINES: + case TIFFTAG_CLEANFAXDATA: + case TIFFTAG_CONSECUTIVEBADFAXLINES: + return 1; + case TIFFTAG_GROUP3OPTIONS: + if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX3) + return 1; + break; + case TIFFTAG_GROUP4OPTIONS: + if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4) + return 1; + break; + } + break; + case COMPRESSION_JBIG: + /* No codec-specific tags */ + break; + case COMPRESSION_DEFLATE: + case COMPRESSION_ADOBE_DEFLATE: + if (tag == TIFFTAG_PREDICTOR) + return 1; + break; + case COMPRESSION_PIXARLOG: + if (tag == TIFFTAG_PREDICTOR) + return 1; + break; + case COMPRESSION_SGILOG: + case COMPRESSION_SGILOG24: + /* No codec-specific tags */ + break; + case COMPRESSION_LZMA: + if (tag == TIFFTAG_PREDICTOR) + return 1; + break; + + } + return 0; } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_dirread.c b/3rdparty/libtiff/tif_dirread.c index 8beb0a4194..5e62e81315 100644 --- a/3rdparty/libtiff/tif_dirread.c +++ b/3rdparty/libtiff/tif_dirread.c @@ -1,4 +1,4 @@ -/* $Id: tif_dirread.c,v 1.174 2012-02-01 02:24:47 fwarmerdam Exp $ */ +/* $Id: tif_dirread.c,v 1.218 2017-09-09 21:44:42 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -40,6 +40,8 @@ */ #include "tiffiop.h" +#include +#include #define IGNORE 0 /* tag placeholder used below */ #define FAILED_FII ((uint32) -1) @@ -53,14 +55,14 @@ extern void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*); #endif enum TIFFReadDirEntryErr { - TIFFReadDirEntryErrOk = 0, - TIFFReadDirEntryErrCount = 1, - TIFFReadDirEntryErrType = 2, - TIFFReadDirEntryErrIo = 3, - TIFFReadDirEntryErrRange = 4, - TIFFReadDirEntryErrPsdif = 5, - TIFFReadDirEntryErrSizesan = 6, - TIFFReadDirEntryErrAlloc = 7, + TIFFReadDirEntryErrOk = 0, + TIFFReadDirEntryErrCount = 1, + TIFFReadDirEntryErrType = 2, + TIFFReadDirEntryErrIo = 3, + TIFFReadDirEntryErrRange = 4, + TIFFReadDirEntryErrPsdif = 5, + TIFFReadDirEntryErrSizesan = 6, + TIFFReadDirEntryErrAlloc = 7, }; static enum TIFFReadDirEntryErr TIFFReadDirEntryByte(TIFF* tif, TIFFDirEntry* direntry, uint8* value); @@ -166,13 +168,15 @@ static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*); static void ChopUpSingleUncompressedStrip(TIFF*); static uint64 TIFFReadUInt64(const uint8 *value); +static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount ); + typedef union _UInt64Aligned_t { double d; - uint64 l; - uint32 i[2]; - uint16 s[4]; - uint8 c[8]; + uint64 l; + uint32 i[2]; + uint16 s[4]; + uint8 c[8]; } UInt64Aligned_t; /* @@ -180,3042 +184,3131 @@ typedef union _UInt64Aligned_t */ static uint64 TIFFReadUInt64(const uint8 *value) { - UInt64Aligned_t result; + UInt64Aligned_t result; - result.c[0]=value[0]; - result.c[1]=value[1]; - result.c[2]=value[2]; - result.c[3]=value[3]; - result.c[4]=value[4]; - result.c[5]=value[5]; - result.c[6]=value[6]; - result.c[7]=value[7]; + result.c[0]=value[0]; + result.c[1]=value[1]; + result.c[2]=value[2]; + result.c[3]=value[3]; + result.c[4]=value[4]; + result.c[5]=value[5]; + result.c[6]=value[6]; + result.c[7]=value[7]; - return result.l; + return result.l; } static enum TIFFReadDirEntryErr TIFFReadDirEntryByte(TIFF* tif, TIFFDirEntry* direntry, uint8* value) { - enum TIFFReadDirEntryErr err; - if (direntry->tdir_count!=1) - return(TIFFReadDirEntryErrCount); - switch (direntry->tdir_type) - { - case TIFF_BYTE: - TIFFReadDirEntryCheckedByte(tif,direntry,value); - return(TIFFReadDirEntryErrOk); - case TIFF_SBYTE: - { - int8 m; - TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeByteSbyte(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint8)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SHORT: - { - uint16 m; - TIFFReadDirEntryCheckedShort(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeByteShort(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint8)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SSHORT: - { - int16 m; - TIFFReadDirEntryCheckedSshort(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeByteSshort(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint8)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG: - { - uint32 m; - TIFFReadDirEntryCheckedLong(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeByteLong(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint8)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG: - { - int32 m; - TIFFReadDirEntryCheckedSlong(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeByteSlong(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint8)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG8: - { - uint64 m; - err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - err=TIFFReadDirEntryCheckRangeByteLong8(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint8)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG8: - { - int64 m; - err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - err=TIFFReadDirEntryCheckRangeByteSlong8(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint8)m; - return(TIFFReadDirEntryErrOk); - } - default: - return(TIFFReadDirEntryErrType); - } + enum TIFFReadDirEntryErr err; + if (direntry->tdir_count!=1) + return(TIFFReadDirEntryErrCount); + switch (direntry->tdir_type) + { + case TIFF_BYTE: + TIFFReadDirEntryCheckedByte(tif,direntry,value); + return(TIFFReadDirEntryErrOk); + case TIFF_SBYTE: + { + int8 m; + TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeByteSbyte(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint8)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SHORT: + { + uint16 m; + TIFFReadDirEntryCheckedShort(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeByteShort(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint8)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SSHORT: + { + int16 m; + TIFFReadDirEntryCheckedSshort(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeByteSshort(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint8)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG: + { + uint32 m; + TIFFReadDirEntryCheckedLong(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeByteLong(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint8)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG: + { + int32 m; + TIFFReadDirEntryCheckedSlong(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeByteSlong(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint8)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG8: + { + uint64 m; + err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + err=TIFFReadDirEntryCheckRangeByteLong8(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint8)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG8: + { + int64 m; + err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + err=TIFFReadDirEntryCheckRangeByteSlong8(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint8)m; + return(TIFFReadDirEntryErrOk); + } + default: + return(TIFFReadDirEntryErrType); + } } static enum TIFFReadDirEntryErr TIFFReadDirEntryShort(TIFF* tif, TIFFDirEntry* direntry, uint16* value) { - enum TIFFReadDirEntryErr err; - if (direntry->tdir_count!=1) - return(TIFFReadDirEntryErrCount); - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8 m; - TIFFReadDirEntryCheckedByte(tif,direntry,&m); - *value=(uint16)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SBYTE: - { - int8 m; - TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeShortSbyte(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint16)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SHORT: - TIFFReadDirEntryCheckedShort(tif,direntry,value); - return(TIFFReadDirEntryErrOk); - case TIFF_SSHORT: - { - int16 m; - TIFFReadDirEntryCheckedSshort(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeShortSshort(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint16)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG: - { - uint32 m; - TIFFReadDirEntryCheckedLong(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeShortLong(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint16)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG: - { - int32 m; - TIFFReadDirEntryCheckedSlong(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeShortSlong(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint16)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG8: - { - uint64 m; - err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - err=TIFFReadDirEntryCheckRangeShortLong8(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint16)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG8: - { - int64 m; - err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - err=TIFFReadDirEntryCheckRangeShortSlong8(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint16)m; - return(TIFFReadDirEntryErrOk); - } - default: - return(TIFFReadDirEntryErrType); - } + enum TIFFReadDirEntryErr err; + if (direntry->tdir_count!=1) + return(TIFFReadDirEntryErrCount); + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8 m; + TIFFReadDirEntryCheckedByte(tif,direntry,&m); + *value=(uint16)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SBYTE: + { + int8 m; + TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeShortSbyte(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint16)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SHORT: + TIFFReadDirEntryCheckedShort(tif,direntry,value); + return(TIFFReadDirEntryErrOk); + case TIFF_SSHORT: + { + int16 m; + TIFFReadDirEntryCheckedSshort(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeShortSshort(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint16)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG: + { + uint32 m; + TIFFReadDirEntryCheckedLong(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeShortLong(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint16)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG: + { + int32 m; + TIFFReadDirEntryCheckedSlong(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeShortSlong(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint16)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG8: + { + uint64 m; + err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + err=TIFFReadDirEntryCheckRangeShortLong8(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint16)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG8: + { + int64 m; + err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + err=TIFFReadDirEntryCheckRangeShortSlong8(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint16)m; + return(TIFFReadDirEntryErrOk); + } + default: + return(TIFFReadDirEntryErrType); + } } static enum TIFFReadDirEntryErr TIFFReadDirEntryLong(TIFF* tif, TIFFDirEntry* direntry, uint32* value) { - enum TIFFReadDirEntryErr err; - if (direntry->tdir_count!=1) - return(TIFFReadDirEntryErrCount); - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8 m; - TIFFReadDirEntryCheckedByte(tif,direntry,&m); - *value=(uint32)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SBYTE: - { - int8 m; - TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeLongSbyte(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint32)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SHORT: - { - uint16 m; - TIFFReadDirEntryCheckedShort(tif,direntry,&m); - *value=(uint32)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SSHORT: - { - int16 m; - TIFFReadDirEntryCheckedSshort(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeLongSshort(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint32)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG: - TIFFReadDirEntryCheckedLong(tif,direntry,value); - return(TIFFReadDirEntryErrOk); - case TIFF_SLONG: - { - int32 m; - TIFFReadDirEntryCheckedSlong(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeLongSlong(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint32)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG8: - { - uint64 m; - err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - err=TIFFReadDirEntryCheckRangeLongLong8(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint32)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG8: - { - int64 m; - err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - err=TIFFReadDirEntryCheckRangeLongSlong8(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint32)m; - return(TIFFReadDirEntryErrOk); - } - default: - return(TIFFReadDirEntryErrType); - } + enum TIFFReadDirEntryErr err; + if (direntry->tdir_count!=1) + return(TIFFReadDirEntryErrCount); + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8 m; + TIFFReadDirEntryCheckedByte(tif,direntry,&m); + *value=(uint32)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SBYTE: + { + int8 m; + TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeLongSbyte(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint32)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SHORT: + { + uint16 m; + TIFFReadDirEntryCheckedShort(tif,direntry,&m); + *value=(uint32)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SSHORT: + { + int16 m; + TIFFReadDirEntryCheckedSshort(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeLongSshort(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint32)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG: + TIFFReadDirEntryCheckedLong(tif,direntry,value); + return(TIFFReadDirEntryErrOk); + case TIFF_SLONG: + { + int32 m; + TIFFReadDirEntryCheckedSlong(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeLongSlong(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint32)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG8: + { + uint64 m; + err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + err=TIFFReadDirEntryCheckRangeLongLong8(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint32)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG8: + { + int64 m; + err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + err=TIFFReadDirEntryCheckRangeLongSlong8(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint32)m; + return(TIFFReadDirEntryErrOk); + } + default: + return(TIFFReadDirEntryErrType); + } } static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8(TIFF* tif, TIFFDirEntry* direntry, uint64* value) { - enum TIFFReadDirEntryErr err; - if (direntry->tdir_count!=1) - return(TIFFReadDirEntryErrCount); - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8 m; - TIFFReadDirEntryCheckedByte(tif,direntry,&m); - *value=(uint64)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SBYTE: - { - int8 m; - TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeLong8Sbyte(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint64)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SHORT: - { - uint16 m; - TIFFReadDirEntryCheckedShort(tif,direntry,&m); - *value=(uint64)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SSHORT: - { - int16 m; - TIFFReadDirEntryCheckedSshort(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeLong8Sshort(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint64)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG: - { - uint32 m; - TIFFReadDirEntryCheckedLong(tif,direntry,&m); - *value=(uint64)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG: - { - int32 m; - TIFFReadDirEntryCheckedSlong(tif,direntry,&m); - err=TIFFReadDirEntryCheckRangeLong8Slong(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint64)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG8: - err=TIFFReadDirEntryCheckedLong8(tif,direntry,value); - return(err); - case TIFF_SLONG8: - { - int64 m; - err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - err=TIFFReadDirEntryCheckRangeLong8Slong8(m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(uint64)m; - return(TIFFReadDirEntryErrOk); - } - default: - return(TIFFReadDirEntryErrType); - } + enum TIFFReadDirEntryErr err; + if (direntry->tdir_count!=1) + return(TIFFReadDirEntryErrCount); + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8 m; + TIFFReadDirEntryCheckedByte(tif,direntry,&m); + *value=(uint64)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SBYTE: + { + int8 m; + TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeLong8Sbyte(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint64)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SHORT: + { + uint16 m; + TIFFReadDirEntryCheckedShort(tif,direntry,&m); + *value=(uint64)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SSHORT: + { + int16 m; + TIFFReadDirEntryCheckedSshort(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeLong8Sshort(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint64)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG: + { + uint32 m; + TIFFReadDirEntryCheckedLong(tif,direntry,&m); + *value=(uint64)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG: + { + int32 m; + TIFFReadDirEntryCheckedSlong(tif,direntry,&m); + err=TIFFReadDirEntryCheckRangeLong8Slong(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint64)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG8: + err=TIFFReadDirEntryCheckedLong8(tif,direntry,value); + return(err); + case TIFF_SLONG8: + { + int64 m; + err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + err=TIFFReadDirEntryCheckRangeLong8Slong8(m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(uint64)m; + return(TIFFReadDirEntryErrOk); + } + default: + return(TIFFReadDirEntryErrType); + } } static enum TIFFReadDirEntryErr TIFFReadDirEntryFloat(TIFF* tif, TIFFDirEntry* direntry, float* value) { - enum TIFFReadDirEntryErr err; - if (direntry->tdir_count!=1) - return(TIFFReadDirEntryErrCount); - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8 m; - TIFFReadDirEntryCheckedByte(tif,direntry,&m); - *value=(float)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SBYTE: - { - int8 m; - TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); - *value=(float)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SHORT: - { - uint16 m; - TIFFReadDirEntryCheckedShort(tif,direntry,&m); - *value=(float)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SSHORT: - { - int16 m; - TIFFReadDirEntryCheckedSshort(tif,direntry,&m); - *value=(float)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG: - { - uint32 m; - TIFFReadDirEntryCheckedLong(tif,direntry,&m); - *value=(float)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG: - { - int32 m; - TIFFReadDirEntryCheckedSlong(tif,direntry,&m); - *value=(float)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG8: - { - uint64 m; - err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); + enum TIFFReadDirEntryErr err; + if (direntry->tdir_count!=1) + return(TIFFReadDirEntryErrCount); + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8 m; + TIFFReadDirEntryCheckedByte(tif,direntry,&m); + *value=(float)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SBYTE: + { + int8 m; + TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); + *value=(float)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SHORT: + { + uint16 m; + TIFFReadDirEntryCheckedShort(tif,direntry,&m); + *value=(float)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SSHORT: + { + int16 m; + TIFFReadDirEntryCheckedSshort(tif,direntry,&m); + *value=(float)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG: + { + uint32 m; + TIFFReadDirEntryCheckedLong(tif,direntry,&m); + *value=(float)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG: + { + int32 m; + TIFFReadDirEntryCheckedSlong(tif,direntry,&m); + *value=(float)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG8: + { + uint64 m; + err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); #if defined(__WIN32__) && (_MSC_VER < 1500) - /* - * XXX: MSVC 6.0 does not support conversion - * of 64-bit integers into floating point - * values. - */ - *value = _TIFFUInt64ToFloat(m); + /* + * XXX: MSVC 6.0 does not support conversion + * of 64-bit integers into floating point + * values. + */ + *value = _TIFFUInt64ToFloat(m); #else - *value=(float)m; + *value=(float)m; #endif - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG8: - { - int64 m; - err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(float)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_RATIONAL: - { - double m; - err=TIFFReadDirEntryCheckedRational(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(float)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SRATIONAL: - { - double m; - err=TIFFReadDirEntryCheckedSrational(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(float)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_FLOAT: - TIFFReadDirEntryCheckedFloat(tif,direntry,value); - return(TIFFReadDirEntryErrOk); - case TIFF_DOUBLE: - { - double m; - err=TIFFReadDirEntryCheckedDouble(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(float)m; - return(TIFFReadDirEntryErrOk); - } - default: - return(TIFFReadDirEntryErrType); - } + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG8: + { + int64 m; + err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(float)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_RATIONAL: + { + double m; + err=TIFFReadDirEntryCheckedRational(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(float)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SRATIONAL: + { + double m; + err=TIFFReadDirEntryCheckedSrational(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(float)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_FLOAT: + TIFFReadDirEntryCheckedFloat(tif,direntry,value); + return(TIFFReadDirEntryErrOk); + case TIFF_DOUBLE: + { + double m; + err=TIFFReadDirEntryCheckedDouble(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + if ((m > FLT_MAX) || (m < FLT_MIN)) + return(TIFFReadDirEntryErrRange); + *value=(float)m; + return(TIFFReadDirEntryErrOk); + } + default: + return(TIFFReadDirEntryErrType); + } } static enum TIFFReadDirEntryErr TIFFReadDirEntryDouble(TIFF* tif, TIFFDirEntry* direntry, double* value) { - enum TIFFReadDirEntryErr err; - if (direntry->tdir_count!=1) - return(TIFFReadDirEntryErrCount); - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8 m; - TIFFReadDirEntryCheckedByte(tif,direntry,&m); - *value=(double)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SBYTE: - { - int8 m; - TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); - *value=(double)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SHORT: - { - uint16 m; - TIFFReadDirEntryCheckedShort(tif,direntry,&m); - *value=(double)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SSHORT: - { - int16 m; - TIFFReadDirEntryCheckedSshort(tif,direntry,&m); - *value=(double)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG: - { - uint32 m; - TIFFReadDirEntryCheckedLong(tif,direntry,&m); - *value=(double)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG: - { - int32 m; - TIFFReadDirEntryCheckedSlong(tif,direntry,&m); - *value=(double)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_LONG8: - { - uint64 m; - err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); + enum TIFFReadDirEntryErr err; + if (direntry->tdir_count!=1) + return(TIFFReadDirEntryErrCount); + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8 m; + TIFFReadDirEntryCheckedByte(tif,direntry,&m); + *value=(double)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SBYTE: + { + int8 m; + TIFFReadDirEntryCheckedSbyte(tif,direntry,&m); + *value=(double)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SHORT: + { + uint16 m; + TIFFReadDirEntryCheckedShort(tif,direntry,&m); + *value=(double)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SSHORT: + { + int16 m; + TIFFReadDirEntryCheckedSshort(tif,direntry,&m); + *value=(double)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG: + { + uint32 m; + TIFFReadDirEntryCheckedLong(tif,direntry,&m); + *value=(double)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG: + { + int32 m; + TIFFReadDirEntryCheckedSlong(tif,direntry,&m); + *value=(double)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG8: + { + uint64 m; + err=TIFFReadDirEntryCheckedLong8(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); #if defined(__WIN32__) && (_MSC_VER < 1500) - /* - * XXX: MSVC 6.0 does not support conversion - * of 64-bit integers into floating point - * values. - */ - *value = _TIFFUInt64ToDouble(m); + /* + * XXX: MSVC 6.0 does not support conversion + * of 64-bit integers into floating point + * values. + */ + *value = _TIFFUInt64ToDouble(m); #else - *value = (double)m; + *value = (double)m; #endif - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG8: - { - int64 m; - err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - *value=(double)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_RATIONAL: - err=TIFFReadDirEntryCheckedRational(tif,direntry,value); - return(err); - case TIFF_SRATIONAL: - err=TIFFReadDirEntryCheckedSrational(tif,direntry,value); - return(err); - case TIFF_FLOAT: - { - float m; - TIFFReadDirEntryCheckedFloat(tif,direntry,&m); - *value=(double)m; - return(TIFFReadDirEntryErrOk); - } - case TIFF_DOUBLE: - err=TIFFReadDirEntryCheckedDouble(tif,direntry,value); - return(err); - default: - return(TIFFReadDirEntryErrType); - } + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG8: + { + int64 m; + err=TIFFReadDirEntryCheckedSlong8(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + *value=(double)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_RATIONAL: + err=TIFFReadDirEntryCheckedRational(tif,direntry,value); + return(err); + case TIFF_SRATIONAL: + err=TIFFReadDirEntryCheckedSrational(tif,direntry,value); + return(err); + case TIFF_FLOAT: + { + float m; + TIFFReadDirEntryCheckedFloat(tif,direntry,&m); + *value=(double)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_DOUBLE: + err=TIFFReadDirEntryCheckedDouble(tif,direntry,value); + return(err); + default: + return(TIFFReadDirEntryErrType); + } } static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8(TIFF* tif, TIFFDirEntry* direntry, uint64* value) { - enum TIFFReadDirEntryErr err; - if (direntry->tdir_count!=1) - return(TIFFReadDirEntryErrCount); - switch (direntry->tdir_type) - { - case TIFF_LONG: - case TIFF_IFD: + enum TIFFReadDirEntryErr err; + if (direntry->tdir_count!=1) + return(TIFFReadDirEntryErrCount); + switch (direntry->tdir_type) + { + case TIFF_LONG: + case TIFF_IFD: + { + uint32 m; + TIFFReadDirEntryCheckedLong(tif,direntry,&m); + *value=(uint64)m; + return(TIFFReadDirEntryErrOk); + } + case TIFF_LONG8: + case TIFF_IFD8: + err=TIFFReadDirEntryCheckedLong8(tif,direntry,value); + return(err); + default: + return(TIFFReadDirEntryErrType); + } +} + + +#define INITIAL_THRESHOLD (1024 * 1024) +#define THRESHOLD_MULTIPLIER 10 +#define MAX_THRESHOLD (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * INITIAL_THRESHOLD) + +static enum TIFFReadDirEntryErr TIFFReadDirEntryDataAndRealloc( + TIFF* tif, uint64 offset, tmsize_t size, void** pdest) +{ +#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8 + tmsize_t threshold = INITIAL_THRESHOLD; +#endif + tmsize_t already_read = 0; + + assert( !isMapped(tif) ); + + if (!SeekOK(tif,offset)) + return(TIFFReadDirEntryErrIo); + + /* On 64 bit processes, read first a maximum of 1 MB, then 10 MB, etc */ + /* so as to avoid allocating too much memory in case the file is too */ + /* short. We could ask for the file size, but this might be */ + /* expensive with some I/O layers (think of reading a gzipped file) */ + /* Restrict to 64 bit processes, so as to avoid reallocs() */ + /* on 32 bit processes where virtual memory is scarce. */ + while( already_read < size ) + { + void* new_dest; + tmsize_t bytes_read; + tmsize_t to_read = size - already_read; +#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8 + if( to_read >= threshold && threshold < MAX_THRESHOLD ) { - uint32 m; - TIFFReadDirEntryCheckedLong(tif,direntry,&m); - *value=(uint64)m; - return(TIFFReadDirEntryErrOk); + to_read = threshold; + threshold *= THRESHOLD_MULTIPLIER; } - case TIFF_LONG8: - case TIFF_IFD8: - err=TIFFReadDirEntryCheckedLong8(tif,direntry,value); - return(err); - default: - return(TIFFReadDirEntryErrType); - } +#endif + + new_dest = (uint8*) _TIFFrealloc( + *pdest, already_read + to_read); + if( new_dest == NULL ) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Failed to allocate memory for %s " + "(%ld elements of %ld bytes each)", + "TIFFReadDirEntryArray", + (long) 1, (long) (already_read + to_read)); + return TIFFReadDirEntryErrAlloc; + } + *pdest = new_dest; + + bytes_read = TIFFReadFile(tif, + (char*)*pdest + already_read, to_read); + already_read += bytes_read; + if (bytes_read != to_read) { + return TIFFReadDirEntryErrIo; + } + } + return TIFFReadDirEntryErrOk; +} + +static enum TIFFReadDirEntryErr TIFFReadDirEntryArrayWithLimit( + TIFF* tif, TIFFDirEntry* direntry, uint32* count, uint32 desttypesize, + void** value, uint64 maxcount) +{ + int typesize; + uint32 datasize; + void* data; + uint64 target_count64; + typesize=TIFFDataWidth(direntry->tdir_type); + + target_count64 = (direntry->tdir_count > maxcount) ? + maxcount : direntry->tdir_count; + + if ((target_count64==0)||(typesize==0)) + { + *value=0; + return(TIFFReadDirEntryErrOk); + } + (void) desttypesize; + + /* + * As a sanity check, make sure we have no more than a 2GB tag array + * in either the current data type or the dest data type. This also + * avoids problems with overflow of tmsize_t on 32bit systems. + */ + if ((uint64)(2147483647/typesize)0); + + if( isMapped(tif) && datasize > (uint32)tif->tif_size ) + return TIFFReadDirEntryErrIo; + + if( !isMapped(tif) && + (((tif->tif_flags&TIFF_BIGTIFF) && datasize > 8) || + (!(tif->tif_flags&TIFF_BIGTIFF) && datasize > 4)) ) + { + data = NULL; + } + else + { + data=_TIFFCheckMalloc(tif, *count, typesize, "ReadDirEntryArray"); + if (data==0) + return(TIFFReadDirEntryErrAlloc); + } + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + if (datasize<=4) + _TIFFmemcpy(data,&direntry->tdir_offset,datasize); + else + { + enum TIFFReadDirEntryErr err; + uint32 offset = direntry->tdir_offset.toff_long; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&offset); + if( isMapped(tif) ) + err=TIFFReadDirEntryData(tif,(uint64)offset,(tmsize_t)datasize,data); + else + err=TIFFReadDirEntryDataAndRealloc(tif,(uint64)offset,(tmsize_t)datasize,&data); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(data); + return(err); + } + } + } + else + { + if (datasize<=8) + _TIFFmemcpy(data,&direntry->tdir_offset,datasize); + else + { + enum TIFFReadDirEntryErr err; + uint64 offset = direntry->tdir_offset.toff_long8; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8(&offset); + if( isMapped(tif) ) + err=TIFFReadDirEntryData(tif,(uint64)offset,(tmsize_t)datasize,data); + else + err=TIFFReadDirEntryDataAndRealloc(tif,(uint64)offset,(tmsize_t)datasize,&data); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(data); + return(err); + } + } + } + *value=data; + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryArray(TIFF* tif, TIFFDirEntry* direntry, uint32* count, uint32 desttypesize, void** value) { - int typesize; - uint32 datasize; - void* data; - typesize=TIFFDataWidth(direntry->tdir_type); - if ((direntry->tdir_count==0)||(typesize==0)) - { - *value=0; - return(TIFFReadDirEntryErrOk); - } - (void) desttypesize; - - /* - * As a sanity check, make sure we have no more than a 2GB tag array - * in either the current data type or the dest data type. This also - * avoids problems with overflow of tmsize_t on 32bit systems. - */ - if ((uint64)(2147483647/typesize)tdir_count) - return(TIFFReadDirEntryErrSizesan); - if ((uint64)(2147483647/desttypesize)tdir_count) - return(TIFFReadDirEntryErrSizesan); - - *count=(uint32)direntry->tdir_count; - datasize=(*count)*typesize; - assert((tmsize_t)datasize>0); - data=_TIFFCheckMalloc(tif, *count, typesize, "ReadDirEntryArray"); - if (data==0) - return(TIFFReadDirEntryErrAlloc); - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - if (datasize<=4) - _TIFFmemcpy(data,&direntry->tdir_offset,datasize); - else - { - enum TIFFReadDirEntryErr err; - uint32 offset = direntry->tdir_offset.toff_long; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&offset); - err=TIFFReadDirEntryData(tif,(uint64)offset,(tmsize_t)datasize,data); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(data); - return(err); - } - } - } - else - { - if (datasize<=8) - _TIFFmemcpy(data,&direntry->tdir_offset,datasize); - else - { - enum TIFFReadDirEntryErr err; - uint64 offset = direntry->tdir_offset.toff_long8; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8(&offset); - err=TIFFReadDirEntryData(tif,offset,(tmsize_t)datasize,data); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(data); - return(err); - } - } - } - *value=data; - return(TIFFReadDirEntryErrOk); + return TIFFReadDirEntryArrayWithLimit(tif, direntry, count, + desttypesize, value, ~((uint64)0)); } static enum TIFFReadDirEntryErr TIFFReadDirEntryByteArray(TIFF* tif, TIFFDirEntry* direntry, uint8** value) { - enum TIFFReadDirEntryErr err; - uint32 count; - void* origdata; - uint8* data; - switch (direntry->tdir_type) - { - case TIFF_ASCII: - case TIFF_UNDEFINED: - case TIFF_BYTE: - case TIFF_SBYTE: - case TIFF_SHORT: - case TIFF_SSHORT: - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_LONG8: - case TIFF_SLONG8: - break; - default: - return(TIFFReadDirEntryErrType); - } - err=TIFFReadDirEntryArray(tif,direntry,&count,1,&origdata); - if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) - { - *value=0; - return(err); - } - switch (direntry->tdir_type) - { - case TIFF_ASCII: - case TIFF_UNDEFINED: - case TIFF_BYTE: - *value=(uint8*)origdata; - return(TIFFReadDirEntryErrOk); - case TIFF_SBYTE: - { - int8* m; - uint32 n; - m=(int8*)origdata; - for (n=0; ntdir_type) - { - case TIFF_SHORT: - { - uint16* ma; - uint8* mb; - uint32 n; - ma=(uint16*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort(ma); - err=TIFFReadDirEntryCheckRangeByteShort(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint8)(*ma++); - } - } - break; - case TIFF_SSHORT: - { - int16* ma; - uint8* mb; - uint32 n; - ma=(int16*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)ma); - err=TIFFReadDirEntryCheckRangeByteSshort(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint8)(*ma++); - } - } - break; - case TIFF_LONG: - { - uint32* ma; - uint8* mb; - uint32 n; - ma=(uint32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - err=TIFFReadDirEntryCheckRangeByteLong(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint8)(*ma++); - } - } - break; - case TIFF_SLONG: - { - int32* ma; - uint8* mb; - uint32 n; - ma=(int32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)ma); - err=TIFFReadDirEntryCheckRangeByteSlong(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint8)(*ma++); - } - } - break; - case TIFF_LONG8: - { - uint64* ma; - uint8* mb; - uint32 n; - ma=(uint64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8(ma); - err=TIFFReadDirEntryCheckRangeByteLong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint8)(*ma++); - } - } - break; - case TIFF_SLONG8: - { - int64* ma; - uint8* mb; - uint32 n; - ma=(int64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)ma); - err=TIFFReadDirEntryCheckRangeByteSlong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint8)(*ma++); - } - } - break; - } - _TIFFfree(origdata); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(data); - return(err); - } - *value=data; - return(TIFFReadDirEntryErrOk); + enum TIFFReadDirEntryErr err; + uint32 count; + void* origdata; + uint8* data; + switch (direntry->tdir_type) + { + case TIFF_ASCII: + case TIFF_UNDEFINED: + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_LONG8: + case TIFF_SLONG8: + break; + default: + return(TIFFReadDirEntryErrType); + } + err=TIFFReadDirEntryArray(tif,direntry,&count,1,&origdata); + if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) + { + *value=0; + return(err); + } + switch (direntry->tdir_type) + { + case TIFF_ASCII: + case TIFF_UNDEFINED: + case TIFF_BYTE: + *value=(uint8*)origdata; + return(TIFFReadDirEntryErrOk); + case TIFF_SBYTE: + { + int8* m; + uint32 n; + m=(int8*)origdata; + for (n=0; ntdir_type) + { + case TIFF_SHORT: + { + uint16* ma; + uint8* mb; + uint32 n; + ma=(uint16*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort(ma); + err=TIFFReadDirEntryCheckRangeByteShort(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint8)(*ma++); + } + } + break; + case TIFF_SSHORT: + { + int16* ma; + uint8* mb; + uint32 n; + ma=(int16*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)ma); + err=TIFFReadDirEntryCheckRangeByteSshort(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint8)(*ma++); + } + } + break; + case TIFF_LONG: + { + uint32* ma; + uint8* mb; + uint32 n; + ma=(uint32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + err=TIFFReadDirEntryCheckRangeByteLong(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint8)(*ma++); + } + } + break; + case TIFF_SLONG: + { + int32* ma; + uint8* mb; + uint32 n; + ma=(int32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)ma); + err=TIFFReadDirEntryCheckRangeByteSlong(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint8)(*ma++); + } + } + break; + case TIFF_LONG8: + { + uint64* ma; + uint8* mb; + uint32 n; + ma=(uint64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8(ma); + err=TIFFReadDirEntryCheckRangeByteLong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint8)(*ma++); + } + } + break; + case TIFF_SLONG8: + { + int64* ma; + uint8* mb; + uint32 n; + ma=(int64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)ma); + err=TIFFReadDirEntryCheckRangeByteSlong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint8)(*ma++); + } + } + break; + } + _TIFFfree(origdata); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(data); + return(err); + } + *value=data; + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntrySbyteArray(TIFF* tif, TIFFDirEntry* direntry, int8** value) { - enum TIFFReadDirEntryErr err; - uint32 count; - void* origdata; - int8* data; - switch (direntry->tdir_type) - { - case TIFF_UNDEFINED: - case TIFF_BYTE: - case TIFF_SBYTE: - case TIFF_SHORT: - case TIFF_SSHORT: - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_LONG8: - case TIFF_SLONG8: - break; - default: - return(TIFFReadDirEntryErrType); - } - err=TIFFReadDirEntryArray(tif,direntry,&count,1,&origdata); - if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) - { - *value=0; - return(err); - } - switch (direntry->tdir_type) - { - case TIFF_UNDEFINED: - case TIFF_BYTE: - { - uint8* m; - uint32 n; - m=(uint8*)origdata; - for (n=0; ntdir_type) - { - case TIFF_SHORT: - { - uint16* ma; - int8* mb; - uint32 n; - ma=(uint16*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort(ma); - err=TIFFReadDirEntryCheckRangeSbyteShort(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int8)(*ma++); - } - } - break; - case TIFF_SSHORT: - { - int16* ma; - int8* mb; - uint32 n; - ma=(int16*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)ma); - err=TIFFReadDirEntryCheckRangeSbyteSshort(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int8)(*ma++); - } - } - break; - case TIFF_LONG: - { - uint32* ma; - int8* mb; - uint32 n; - ma=(uint32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - err=TIFFReadDirEntryCheckRangeSbyteLong(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int8)(*ma++); - } - } - break; - case TIFF_SLONG: - { - int32* ma; - int8* mb; - uint32 n; - ma=(int32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)ma); - err=TIFFReadDirEntryCheckRangeSbyteSlong(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int8)(*ma++); - } - } - break; - case TIFF_LONG8: - { - uint64* ma; - int8* mb; - uint32 n; - ma=(uint64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8(ma); - err=TIFFReadDirEntryCheckRangeSbyteLong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int8)(*ma++); - } - } - break; - case TIFF_SLONG8: - { - int64* ma; - int8* mb; - uint32 n; - ma=(int64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)ma); - err=TIFFReadDirEntryCheckRangeSbyteSlong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int8)(*ma++); - } - } - break; - } - _TIFFfree(origdata); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(data); - return(err); - } - *value=data; - return(TIFFReadDirEntryErrOk); + enum TIFFReadDirEntryErr err; + uint32 count; + void* origdata; + int8* data; + switch (direntry->tdir_type) + { + case TIFF_UNDEFINED: + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_LONG8: + case TIFF_SLONG8: + break; + default: + return(TIFFReadDirEntryErrType); + } + err=TIFFReadDirEntryArray(tif,direntry,&count,1,&origdata); + if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) + { + *value=0; + return(err); + } + switch (direntry->tdir_type) + { + case TIFF_UNDEFINED: + case TIFF_BYTE: + { + uint8* m; + uint32 n; + m=(uint8*)origdata; + for (n=0; ntdir_type) + { + case TIFF_SHORT: + { + uint16* ma; + int8* mb; + uint32 n; + ma=(uint16*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort(ma); + err=TIFFReadDirEntryCheckRangeSbyteShort(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int8)(*ma++); + } + } + break; + case TIFF_SSHORT: + { + int16* ma; + int8* mb; + uint32 n; + ma=(int16*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)ma); + err=TIFFReadDirEntryCheckRangeSbyteSshort(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int8)(*ma++); + } + } + break; + case TIFF_LONG: + { + uint32* ma; + int8* mb; + uint32 n; + ma=(uint32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + err=TIFFReadDirEntryCheckRangeSbyteLong(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int8)(*ma++); + } + } + break; + case TIFF_SLONG: + { + int32* ma; + int8* mb; + uint32 n; + ma=(int32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)ma); + err=TIFFReadDirEntryCheckRangeSbyteSlong(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int8)(*ma++); + } + } + break; + case TIFF_LONG8: + { + uint64* ma; + int8* mb; + uint32 n; + ma=(uint64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8(ma); + err=TIFFReadDirEntryCheckRangeSbyteLong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int8)(*ma++); + } + } + break; + case TIFF_SLONG8: + { + int64* ma; + int8* mb; + uint32 n; + ma=(int64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)ma); + err=TIFFReadDirEntryCheckRangeSbyteSlong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int8)(*ma++); + } + } + break; + } + _TIFFfree(origdata); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(data); + return(err); + } + *value=data; + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryShortArray(TIFF* tif, TIFFDirEntry* direntry, uint16** value) { - enum TIFFReadDirEntryErr err; - uint32 count; - void* origdata; - uint16* data; - switch (direntry->tdir_type) - { - case TIFF_BYTE: - case TIFF_SBYTE: - case TIFF_SHORT: - case TIFF_SSHORT: - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_LONG8: - case TIFF_SLONG8: - break; - default: - return(TIFFReadDirEntryErrType); - } - err=TIFFReadDirEntryArray(tif,direntry,&count,2,&origdata); - if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) - { - *value=0; - return(err); - } - switch (direntry->tdir_type) - { - case TIFF_SHORT: - *value=(uint16*)origdata; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfShort(*value,count); - return(TIFFReadDirEntryErrOk); - case TIFF_SSHORT: - { - int16* m; - uint32 n; - m=(int16*)origdata; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)m); - err=TIFFReadDirEntryCheckRangeShortSshort(*m); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(origdata); - return(err); - } - m++; - } - *value=(uint16*)origdata; - return(TIFFReadDirEntryErrOk); - } - } - data=(uint16*)_TIFFmalloc(count*2); - if (data==0) - { - _TIFFfree(origdata); - return(TIFFReadDirEntryErrAlloc); - } - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8* ma; - uint16* mb; - uint32 n; - ma=(uint8*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - err=TIFFReadDirEntryCheckRangeShortLong(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint16)(*ma++); - } - } - break; - case TIFF_SLONG: - { - int32* ma; - uint16* mb; - uint32 n; - ma=(int32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)ma); - err=TIFFReadDirEntryCheckRangeShortSlong(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint16)(*ma++); - } - } - break; - case TIFF_LONG8: - { - uint64* ma; - uint16* mb; - uint32 n; - ma=(uint64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8(ma); - err=TIFFReadDirEntryCheckRangeShortLong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint16)(*ma++); - } - } - break; - case TIFF_SLONG8: - { - int64* ma; - uint16* mb; - uint32 n; - ma=(int64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)ma); - err=TIFFReadDirEntryCheckRangeShortSlong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint16)(*ma++); - } - } - break; - } - _TIFFfree(origdata); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(data); - return(err); - } - *value=data; - return(TIFFReadDirEntryErrOk); + enum TIFFReadDirEntryErr err; + uint32 count; + void* origdata; + uint16* data; + switch (direntry->tdir_type) + { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_LONG8: + case TIFF_SLONG8: + break; + default: + return(TIFFReadDirEntryErrType); + } + err=TIFFReadDirEntryArray(tif,direntry,&count,2,&origdata); + if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) + { + *value=0; + return(err); + } + switch (direntry->tdir_type) + { + case TIFF_SHORT: + *value=(uint16*)origdata; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfShort(*value,count); + return(TIFFReadDirEntryErrOk); + case TIFF_SSHORT: + { + int16* m; + uint32 n; + m=(int16*)origdata; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)m); + err=TIFFReadDirEntryCheckRangeShortSshort(*m); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(origdata); + return(err); + } + m++; + } + *value=(uint16*)origdata; + return(TIFFReadDirEntryErrOk); + } + } + data=(uint16*)_TIFFmalloc(count*2); + if (data==0) + { + _TIFFfree(origdata); + return(TIFFReadDirEntryErrAlloc); + } + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8* ma; + uint16* mb; + uint32 n; + ma=(uint8*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + err=TIFFReadDirEntryCheckRangeShortLong(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint16)(*ma++); + } + } + break; + case TIFF_SLONG: + { + int32* ma; + uint16* mb; + uint32 n; + ma=(int32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)ma); + err=TIFFReadDirEntryCheckRangeShortSlong(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint16)(*ma++); + } + } + break; + case TIFF_LONG8: + { + uint64* ma; + uint16* mb; + uint32 n; + ma=(uint64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8(ma); + err=TIFFReadDirEntryCheckRangeShortLong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint16)(*ma++); + } + } + break; + case TIFF_SLONG8: + { + int64* ma; + uint16* mb; + uint32 n; + ma=(int64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)ma); + err=TIFFReadDirEntryCheckRangeShortSlong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint16)(*ma++); + } + } + break; + } + _TIFFfree(origdata); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(data); + return(err); + } + *value=data; + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntrySshortArray(TIFF* tif, TIFFDirEntry* direntry, int16** value) { - enum TIFFReadDirEntryErr err; - uint32 count; - void* origdata; - int16* data; - switch (direntry->tdir_type) - { - case TIFF_BYTE: - case TIFF_SBYTE: - case TIFF_SHORT: - case TIFF_SSHORT: - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_LONG8: - case TIFF_SLONG8: - break; - default: - return(TIFFReadDirEntryErrType); - } - err=TIFFReadDirEntryArray(tif,direntry,&count,2,&origdata); - if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) - { - *value=0; - return(err); - } - switch (direntry->tdir_type) - { - case TIFF_SHORT: - { - uint16* m; - uint32 n; - m=(uint16*)origdata; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort(m); - err=TIFFReadDirEntryCheckRangeSshortShort(*m); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(origdata); - return(err); - } - m++; - } - *value=(int16*)origdata; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SSHORT: - *value=(int16*)origdata; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfShort((uint16*)(*value),count); - return(TIFFReadDirEntryErrOk); - } - data=(int16*)_TIFFmalloc(count*2); - if (data==0) - { - _TIFFfree(origdata); - return(TIFFReadDirEntryErrAlloc); - } - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8* ma; - int16* mb; - uint32 n; - ma=(uint8*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - err=TIFFReadDirEntryCheckRangeSshortLong(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int16)(*ma++); - } - } - break; - case TIFF_SLONG: - { - int32* ma; - int16* mb; - uint32 n; - ma=(int32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)ma); - err=TIFFReadDirEntryCheckRangeSshortSlong(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int16)(*ma++); - } - } - break; - case TIFF_LONG8: - { - uint64* ma; - int16* mb; - uint32 n; - ma=(uint64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8(ma); - err=TIFFReadDirEntryCheckRangeSshortLong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int16)(*ma++); - } - } - break; - case TIFF_SLONG8: - { - int64* ma; - int16* mb; - uint32 n; - ma=(int64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)ma); - err=TIFFReadDirEntryCheckRangeSshortSlong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int16)(*ma++); - } - } - break; - } - _TIFFfree(origdata); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(data); - return(err); - } - *value=data; - return(TIFFReadDirEntryErrOk); + enum TIFFReadDirEntryErr err; + uint32 count; + void* origdata; + int16* data; + switch (direntry->tdir_type) + { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_LONG8: + case TIFF_SLONG8: + break; + default: + return(TIFFReadDirEntryErrType); + } + err=TIFFReadDirEntryArray(tif,direntry,&count,2,&origdata); + if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) + { + *value=0; + return(err); + } + switch (direntry->tdir_type) + { + case TIFF_SHORT: + { + uint16* m; + uint32 n; + m=(uint16*)origdata; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort(m); + err=TIFFReadDirEntryCheckRangeSshortShort(*m); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(origdata); + return(err); + } + m++; + } + *value=(int16*)origdata; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SSHORT: + *value=(int16*)origdata; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfShort((uint16*)(*value),count); + return(TIFFReadDirEntryErrOk); + } + data=(int16*)_TIFFmalloc(count*2); + if (data==0) + { + _TIFFfree(origdata); + return(TIFFReadDirEntryErrAlloc); + } + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8* ma; + int16* mb; + uint32 n; + ma=(uint8*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + err=TIFFReadDirEntryCheckRangeSshortLong(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int16)(*ma++); + } + } + break; + case TIFF_SLONG: + { + int32* ma; + int16* mb; + uint32 n; + ma=(int32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)ma); + err=TIFFReadDirEntryCheckRangeSshortSlong(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int16)(*ma++); + } + } + break; + case TIFF_LONG8: + { + uint64* ma; + int16* mb; + uint32 n; + ma=(uint64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8(ma); + err=TIFFReadDirEntryCheckRangeSshortLong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int16)(*ma++); + } + } + break; + case TIFF_SLONG8: + { + int64* ma; + int16* mb; + uint32 n; + ma=(int64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)ma); + err=TIFFReadDirEntryCheckRangeSshortSlong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int16)(*ma++); + } + } + break; + } + _TIFFfree(origdata); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(data); + return(err); + } + *value=data; + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryLongArray(TIFF* tif, TIFFDirEntry* direntry, uint32** value) { - enum TIFFReadDirEntryErr err; - uint32 count; - void* origdata; - uint32* data; - switch (direntry->tdir_type) - { - case TIFF_BYTE: - case TIFF_SBYTE: - case TIFF_SHORT: - case TIFF_SSHORT: - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_LONG8: - case TIFF_SLONG8: - break; - default: - return(TIFFReadDirEntryErrType); - } - err=TIFFReadDirEntryArray(tif,direntry,&count,4,&origdata); - if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) - { - *value=0; - return(err); - } - switch (direntry->tdir_type) - { - case TIFF_LONG: - *value=(uint32*)origdata; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong(*value,count); - return(TIFFReadDirEntryErrOk); - case TIFF_SLONG: - { - int32* m; - uint32 n; - m=(int32*)origdata; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)m); - err=TIFFReadDirEntryCheckRangeLongSlong(*m); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(origdata); - return(err); - } - m++; - } - *value=(uint32*)origdata; - return(TIFFReadDirEntryErrOk); - } - } - data=(uint32*)_TIFFmalloc(count*4); - if (data==0) - { - _TIFFfree(origdata); - return(TIFFReadDirEntryErrAlloc); - } - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8* ma; - uint32* mb; - uint32 n; - ma=(uint8*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort(ma); - *mb++=(uint32)(*ma++); - } - } - break; - case TIFF_SSHORT: - { - int16* ma; - uint32* mb; - uint32 n; - ma=(int16*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)ma); - err=TIFFReadDirEntryCheckRangeLongSshort(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint32)(*ma++); - } - } - break; - case TIFF_LONG8: - { - uint64* ma; - uint32* mb; - uint32 n; - ma=(uint64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8(ma); - err=TIFFReadDirEntryCheckRangeLongLong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint32)(*ma++); - } - } - break; - case TIFF_SLONG8: - { - int64* ma; - uint32* mb; - uint32 n; - ma=(int64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)ma); - err=TIFFReadDirEntryCheckRangeLongSlong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint32)(*ma++); - } - } - break; - } - _TIFFfree(origdata); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(data); - return(err); - } - *value=data; - return(TIFFReadDirEntryErrOk); + enum TIFFReadDirEntryErr err; + uint32 count; + void* origdata; + uint32* data; + switch (direntry->tdir_type) + { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_LONG8: + case TIFF_SLONG8: + break; + default: + return(TIFFReadDirEntryErrType); + } + err=TIFFReadDirEntryArray(tif,direntry,&count,4,&origdata); + if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) + { + *value=0; + return(err); + } + switch (direntry->tdir_type) + { + case TIFF_LONG: + *value=(uint32*)origdata; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong(*value,count); + return(TIFFReadDirEntryErrOk); + case TIFF_SLONG: + { + int32* m; + uint32 n; + m=(int32*)origdata; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)m); + err=TIFFReadDirEntryCheckRangeLongSlong(*m); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(origdata); + return(err); + } + m++; + } + *value=(uint32*)origdata; + return(TIFFReadDirEntryErrOk); + } + } + data=(uint32*)_TIFFmalloc(count*4); + if (data==0) + { + _TIFFfree(origdata); + return(TIFFReadDirEntryErrAlloc); + } + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8* ma; + uint32* mb; + uint32 n; + ma=(uint8*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort(ma); + *mb++=(uint32)(*ma++); + } + } + break; + case TIFF_SSHORT: + { + int16* ma; + uint32* mb; + uint32 n; + ma=(int16*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)ma); + err=TIFFReadDirEntryCheckRangeLongSshort(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint32)(*ma++); + } + } + break; + case TIFF_LONG8: + { + uint64* ma; + uint32* mb; + uint32 n; + ma=(uint64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8(ma); + err=TIFFReadDirEntryCheckRangeLongLong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint32)(*ma++); + } + } + break; + case TIFF_SLONG8: + { + int64* ma; + uint32* mb; + uint32 n; + ma=(int64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)ma); + err=TIFFReadDirEntryCheckRangeLongSlong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint32)(*ma++); + } + } + break; + } + _TIFFfree(origdata); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(data); + return(err); + } + *value=data; + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntrySlongArray(TIFF* tif, TIFFDirEntry* direntry, int32** value) { - enum TIFFReadDirEntryErr err; - uint32 count; - void* origdata; - int32* data; - switch (direntry->tdir_type) - { - case TIFF_BYTE: - case TIFF_SBYTE: - case TIFF_SHORT: - case TIFF_SSHORT: - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_LONG8: - case TIFF_SLONG8: - break; - default: - return(TIFFReadDirEntryErrType); - } - err=TIFFReadDirEntryArray(tif,direntry,&count,4,&origdata); - if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) - { - *value=0; - return(err); - } - switch (direntry->tdir_type) - { - case TIFF_LONG: - { - uint32* m; - uint32 n; - m=(uint32*)origdata; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)m); - err=TIFFReadDirEntryCheckRangeSlongLong(*m); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(origdata); - return(err); - } - m++; - } - *value=(int32*)origdata; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG: - *value=(int32*)origdata; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong((uint32*)(*value),count); - return(TIFFReadDirEntryErrOk); - } - data=(int32*)_TIFFmalloc(count*4); - if (data==0) - { - _TIFFfree(origdata); - return(TIFFReadDirEntryErrAlloc); - } - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8* ma; - int32* mb; - uint32 n; - ma=(uint8*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort(ma); - *mb++=(int32)(*ma++); - } - } - break; - case TIFF_SSHORT: - { - int16* ma; - int32* mb; - uint32 n; - ma=(int16*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)ma); - *mb++=(int32)(*ma++); - } - } - break; - case TIFF_LONG8: - { - uint64* ma; - int32* mb; - uint32 n; - ma=(uint64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8(ma); - err=TIFFReadDirEntryCheckRangeSlongLong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int32)(*ma++); - } - } - break; - case TIFF_SLONG8: - { - int64* ma; - int32* mb; - uint32 n; - ma=(int64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)ma); - err=TIFFReadDirEntryCheckRangeSlongSlong8(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(int32)(*ma++); - } - } - break; - } - _TIFFfree(origdata); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(data); - return(err); - } - *value=data; - return(TIFFReadDirEntryErrOk); + enum TIFFReadDirEntryErr err; + uint32 count; + void* origdata; + int32* data; + switch (direntry->tdir_type) + { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_LONG8: + case TIFF_SLONG8: + break; + default: + return(TIFFReadDirEntryErrType); + } + err=TIFFReadDirEntryArray(tif,direntry,&count,4,&origdata); + if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) + { + *value=0; + return(err); + } + switch (direntry->tdir_type) + { + case TIFF_LONG: + { + uint32* m; + uint32 n; + m=(uint32*)origdata; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)m); + err=TIFFReadDirEntryCheckRangeSlongLong(*m); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(origdata); + return(err); + } + m++; + } + *value=(int32*)origdata; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG: + *value=(int32*)origdata; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong((uint32*)(*value),count); + return(TIFFReadDirEntryErrOk); + } + data=(int32*)_TIFFmalloc(count*4); + if (data==0) + { + _TIFFfree(origdata); + return(TIFFReadDirEntryErrAlloc); + } + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8* ma; + int32* mb; + uint32 n; + ma=(uint8*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort(ma); + *mb++=(int32)(*ma++); + } + } + break; + case TIFF_SSHORT: + { + int16* ma; + int32* mb; + uint32 n; + ma=(int16*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)ma); + *mb++=(int32)(*ma++); + } + } + break; + case TIFF_LONG8: + { + uint64* ma; + int32* mb; + uint32 n; + ma=(uint64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8(ma); + err=TIFFReadDirEntryCheckRangeSlongLong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int32)(*ma++); + } + } + break; + case TIFF_SLONG8: + { + int64* ma; + int32* mb; + uint32 n; + ma=(int64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)ma); + err=TIFFReadDirEntryCheckRangeSlongSlong8(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(int32)(*ma++); + } + } + break; + } + _TIFFfree(origdata); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(data); + return(err); + } + *value=data; + return(TIFFReadDirEntryErrOk); +} + +static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8ArrayWithLimit( + TIFF* tif, TIFFDirEntry* direntry, uint64** value, uint64 maxcount) +{ + enum TIFFReadDirEntryErr err; + uint32 count; + void* origdata; + uint64* data; + switch (direntry->tdir_type) + { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_LONG8: + case TIFF_SLONG8: + break; + default: + return(TIFFReadDirEntryErrType); + } + err=TIFFReadDirEntryArrayWithLimit(tif,direntry,&count,8,&origdata,maxcount); + if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) + { + *value=0; + return(err); + } + switch (direntry->tdir_type) + { + case TIFF_LONG8: + *value=(uint64*)origdata; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong8(*value,count); + return(TIFFReadDirEntryErrOk); + case TIFF_SLONG8: + { + int64* m; + uint32 n; + m=(int64*)origdata; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)m); + err=TIFFReadDirEntryCheckRangeLong8Slong8(*m); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(origdata); + return(err); + } + m++; + } + *value=(uint64*)origdata; + return(TIFFReadDirEntryErrOk); + } + } + data=(uint64*)_TIFFmalloc(count*8); + if (data==0) + { + _TIFFfree(origdata); + return(TIFFReadDirEntryErrAlloc); + } + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8* ma; + uint64* mb; + uint32 n; + ma=(uint8*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort(ma); + *mb++=(uint64)(*ma++); + } + } + break; + case TIFF_SSHORT: + { + int16* ma; + uint64* mb; + uint32 n; + ma=(int16*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)ma); + err=TIFFReadDirEntryCheckRangeLong8Sshort(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint64)(*ma++); + } + } + break; + case TIFF_LONG: + { + uint32* ma; + uint64* mb; + uint32 n; + ma=(uint32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + *mb++=(uint64)(*ma++); + } + } + break; + case TIFF_SLONG: + { + int32* ma; + uint64* mb; + uint32 n; + ma=(int32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)ma); + err=TIFFReadDirEntryCheckRangeLong8Slong(*ma); + if (err!=TIFFReadDirEntryErrOk) + break; + *mb++=(uint64)(*ma++); + } + } + break; + } + _TIFFfree(origdata); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(data); + return(err); + } + *value=data; + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8Array(TIFF* tif, TIFFDirEntry* direntry, uint64** value) { - enum TIFFReadDirEntryErr err; - uint32 count; - void* origdata; - uint64* data; - switch (direntry->tdir_type) - { - case TIFF_BYTE: - case TIFF_SBYTE: - case TIFF_SHORT: - case TIFF_SSHORT: - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_LONG8: - case TIFF_SLONG8: - break; - default: - return(TIFFReadDirEntryErrType); - } - err=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata); - if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) - { - *value=0; - return(err); - } - switch (direntry->tdir_type) - { - case TIFF_LONG8: - *value=(uint64*)origdata; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong8(*value,count); - return(TIFFReadDirEntryErrOk); - case TIFF_SLONG8: - { - int64* m; - uint32 n; - m=(int64*)origdata; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)m); - err=TIFFReadDirEntryCheckRangeLong8Slong8(*m); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(origdata); - return(err); - } - m++; - } - *value=(uint64*)origdata; - return(TIFFReadDirEntryErrOk); - } - } - data=(uint64*)_TIFFmalloc(count*8); - if (data==0) - { - _TIFFfree(origdata); - return(TIFFReadDirEntryErrAlloc); - } - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8* ma; - uint64* mb; - uint32 n; - ma=(uint8*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort(ma); - *mb++=(uint64)(*ma++); - } - } - break; - case TIFF_SSHORT: - { - int16* ma; - uint64* mb; - uint32 n; - ma=(int16*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)ma); - err=TIFFReadDirEntryCheckRangeLong8Sshort(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint64)(*ma++); - } - } - break; - case TIFF_LONG: - { - uint32* ma; - uint64* mb; - uint32 n; - ma=(uint32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - *mb++=(uint64)(*ma++); - } - } - break; - case TIFF_SLONG: - { - int32* ma; - uint64* mb; - uint32 n; - ma=(int32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)ma); - err=TIFFReadDirEntryCheckRangeLong8Slong(*ma); - if (err!=TIFFReadDirEntryErrOk) - break; - *mb++=(uint64)(*ma++); - } - } - break; - } - _TIFFfree(origdata); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(data); - return(err); - } - *value=data; - return(TIFFReadDirEntryErrOk); + return TIFFReadDirEntryLong8ArrayWithLimit(tif, direntry, value, ~((uint64)0)); } static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong8Array(TIFF* tif, TIFFDirEntry* direntry, int64** value) { - enum TIFFReadDirEntryErr err; - uint32 count; - void* origdata; - int64* data; - switch (direntry->tdir_type) - { - case TIFF_BYTE: - case TIFF_SBYTE: - case TIFF_SHORT: - case TIFF_SSHORT: - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_LONG8: - case TIFF_SLONG8: - break; - default: - return(TIFFReadDirEntryErrType); - } - err=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata); - if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) - { - *value=0; - return(err); - } - switch (direntry->tdir_type) - { - case TIFF_LONG8: - { - uint64* m; - uint32 n; - m=(uint64*)origdata; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8(m); - err=TIFFReadDirEntryCheckRangeSlong8Long8(*m); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(origdata); - return(err); - } - m++; - } - *value=(int64*)origdata; - return(TIFFReadDirEntryErrOk); - } - case TIFF_SLONG8: - *value=(int64*)origdata; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong8((uint64*)(*value),count); - return(TIFFReadDirEntryErrOk); - } - data=(int64*)_TIFFmalloc(count*8); - if (data==0) - { - _TIFFfree(origdata); - return(TIFFReadDirEntryErrAlloc); - } - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8* ma; - int64* mb; - uint32 n; - ma=(uint8*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort(ma); - *mb++=(int64)(*ma++); - } - } - break; - case TIFF_SSHORT: - { - int16* ma; - int64* mb; - uint32 n; - ma=(int16*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)ma); - *mb++=(int64)(*ma++); - } - } - break; - case TIFF_LONG: - { - uint32* ma; - int64* mb; - uint32 n; - ma=(uint32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - *mb++=(int64)(*ma++); - } - } - break; - case TIFF_SLONG: - { - int32* ma; - int64* mb; - uint32 n; - ma=(int32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)ma); - *mb++=(int64)(*ma++); - } - } - break; - } - _TIFFfree(origdata); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(data); - return(err); - } - *value=data; - return(TIFFReadDirEntryErrOk); + enum TIFFReadDirEntryErr err; + uint32 count; + void* origdata; + int64* data; + switch (direntry->tdir_type) + { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_LONG8: + case TIFF_SLONG8: + break; + default: + return(TIFFReadDirEntryErrType); + } + err=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata); + if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) + { + *value=0; + return(err); + } + switch (direntry->tdir_type) + { + case TIFF_LONG8: + { + uint64* m; + uint32 n; + m=(uint64*)origdata; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8(m); + err=TIFFReadDirEntryCheckRangeSlong8Long8(*m); + if (err!=TIFFReadDirEntryErrOk) + { + _TIFFfree(origdata); + return(err); + } + m++; + } + *value=(int64*)origdata; + return(TIFFReadDirEntryErrOk); + } + case TIFF_SLONG8: + *value=(int64*)origdata; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong8((uint64*)(*value),count); + return(TIFFReadDirEntryErrOk); + } + data=(int64*)_TIFFmalloc(count*8); + if (data==0) + { + _TIFFfree(origdata); + return(TIFFReadDirEntryErrAlloc); + } + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8* ma; + int64* mb; + uint32 n; + ma=(uint8*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort(ma); + *mb++=(int64)(*ma++); + } + } + break; + case TIFF_SSHORT: + { + int16* ma; + int64* mb; + uint32 n; + ma=(int16*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)ma); + *mb++=(int64)(*ma++); + } + } + break; + case TIFF_LONG: + { + uint32* ma; + int64* mb; + uint32 n; + ma=(uint32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + *mb++=(int64)(*ma++); + } + } + break; + case TIFF_SLONG: + { + int32* ma; + int64* mb; + uint32 n; + ma=(int32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)ma); + *mb++=(int64)(*ma++); + } + } + break; + } + _TIFFfree(origdata); + *value=data; + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryFloatArray(TIFF* tif, TIFFDirEntry* direntry, float** value) { - enum TIFFReadDirEntryErr err; - uint32 count; - void* origdata; - float* data; - switch (direntry->tdir_type) - { - case TIFF_BYTE: - case TIFF_SBYTE: - case TIFF_SHORT: - case TIFF_SSHORT: - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_LONG8: - case TIFF_SLONG8: - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - case TIFF_FLOAT: - case TIFF_DOUBLE: - break; - default: - return(TIFFReadDirEntryErrType); - } - err=TIFFReadDirEntryArray(tif,direntry,&count,4,&origdata); - if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) - { - *value=0; - return(err); - } - switch (direntry->tdir_type) - { - case TIFF_FLOAT: - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong((uint32*)origdata,count); - TIFFCvtIEEEDoubleToNative(tif,count,(float*)origdata); - *value=(float*)origdata; - return(TIFFReadDirEntryErrOk); - } - data=(float*)_TIFFmalloc(count*sizeof(float)); - if (data==0) - { - _TIFFfree(origdata); - return(TIFFReadDirEntryErrAlloc); - } - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8* ma; - float* mb; - uint32 n; - ma=(uint8*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort(ma); - *mb++=(float)(*ma++); - } - } - break; - case TIFF_SSHORT: - { - int16* ma; - float* mb; - uint32 n; - ma=(int16*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)ma); - *mb++=(float)(*ma++); - } - } - break; - case TIFF_LONG: - { - uint32* ma; - float* mb; - uint32 n; - ma=(uint32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - *mb++=(float)(*ma++); - } - } - break; - case TIFF_SLONG: - { - int32* ma; - float* mb; - uint32 n; - ma=(int32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)ma); - *mb++=(float)(*ma++); - } - } - break; - case TIFF_LONG8: - { - uint64* ma; - float* mb; - uint32 n; - ma=(uint64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8(ma); + enum TIFFReadDirEntryErr err; + uint32 count; + void* origdata; + float* data; + switch (direntry->tdir_type) + { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_LONG8: + case TIFF_SLONG8: + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + case TIFF_DOUBLE: + break; + default: + return(TIFFReadDirEntryErrType); + } + err=TIFFReadDirEntryArray(tif,direntry,&count,4,&origdata); + if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) + { + *value=0; + return(err); + } + switch (direntry->tdir_type) + { + case TIFF_FLOAT: + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong((uint32*)origdata,count); + TIFFCvtIEEEDoubleToNative(tif,count,(float*)origdata); + *value=(float*)origdata; + return(TIFFReadDirEntryErrOk); + } + data=(float*)_TIFFmalloc(count*sizeof(float)); + if (data==0) + { + _TIFFfree(origdata); + return(TIFFReadDirEntryErrAlloc); + } + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8* ma; + float* mb; + uint32 n; + ma=(uint8*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort(ma); + *mb++=(float)(*ma++); + } + } + break; + case TIFF_SSHORT: + { + int16* ma; + float* mb; + uint32 n; + ma=(int16*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)ma); + *mb++=(float)(*ma++); + } + } + break; + case TIFF_LONG: + { + uint32* ma; + float* mb; + uint32 n; + ma=(uint32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + *mb++=(float)(*ma++); + } + } + break; + case TIFF_SLONG: + { + int32* ma; + float* mb; + uint32 n; + ma=(int32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)ma); + *mb++=(float)(*ma++); + } + } + break; + case TIFF_LONG8: + { + uint64* ma; + float* mb; + uint32 n; + ma=(uint64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8(ma); #if defined(__WIN32__) && (_MSC_VER < 1500) - /* - * XXX: MSVC 6.0 does not support - * conversion of 64-bit integers into - * floating point values. - */ - *mb++ = _TIFFUInt64ToFloat(*ma++); + /* + * XXX: MSVC 6.0 does not support + * conversion of 64-bit integers into + * floating point values. + */ + *mb++ = _TIFFUInt64ToFloat(*ma++); #else - *mb++ = (float)(*ma++); + *mb++ = (float)(*ma++); #endif - } - } - break; - case TIFF_SLONG8: - { - int64* ma; - float* mb; - uint32 n; - ma=(int64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)ma); - *mb++=(float)(*ma++); - } - } - break; - case TIFF_RATIONAL: - { - uint32* ma; - uint32 maa; - uint32 mab; - float* mb; - uint32 n; - ma=(uint32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - maa=*ma++; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - mab=*ma++; - if (mab==0) - *mb++=0.0; - else - *mb++=(float)maa/(float)mab; - } - } - break; - case TIFF_SRATIONAL: - { - uint32* ma; - int32 maa; - uint32 mab; - float* mb; - uint32 n; - ma=(uint32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - maa=*(int32*)ma; - ma++; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - mab=*ma++; - if (mab==0) - *mb++=0.0; - else - *mb++=(float)maa/(float)mab; - } - } - break; - case TIFF_DOUBLE: - { - double* ma; - float* mb; - uint32 n; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong8((uint64*)origdata,count); - TIFFCvtIEEEDoubleToNative(tif,count,(double*)origdata); - ma=(double*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)ma); + *mb++=(float)(*ma++); + } + } + break; + case TIFF_RATIONAL: + { + uint32* ma; + uint32 maa; + uint32 mab; + float* mb; + uint32 n; + ma=(uint32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + maa=*ma++; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + mab=*ma++; + if (mab==0) + *mb++=0.0; + else + *mb++=(float)maa/(float)mab; + } + } + break; + case TIFF_SRATIONAL: + { + uint32* ma; + int32 maa; + uint32 mab; + float* mb; + uint32 n; + ma=(uint32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + maa=*(int32*)ma; + ma++; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + mab=*ma++; + if (mab==0) + *mb++=0.0; + else + *mb++=(float)maa/(float)mab; + } + } + break; + case TIFF_DOUBLE: + { + double* ma; + float* mb; + uint32 n; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong8((uint64*)origdata,count); + TIFFCvtIEEEDoubleToNative(tif,count,(double*)origdata); + ma=(double*)origdata; + mb=data; + for (n=0; n FLT_MAX ) + val = FLT_MAX; + else if( val < -FLT_MAX ) + val = -FLT_MAX; + *mb++=(float)val; + } + } + break; + } + _TIFFfree(origdata); + *value=data; + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryDoubleArray(TIFF* tif, TIFFDirEntry* direntry, double** value) { - enum TIFFReadDirEntryErr err; - uint32 count; - void* origdata; - double* data; - switch (direntry->tdir_type) - { - case TIFF_BYTE: - case TIFF_SBYTE: - case TIFF_SHORT: - case TIFF_SSHORT: - case TIFF_LONG: - case TIFF_SLONG: - case TIFF_LONG8: - case TIFF_SLONG8: - case TIFF_RATIONAL: - case TIFF_SRATIONAL: - case TIFF_FLOAT: - case TIFF_DOUBLE: - break; - default: - return(TIFFReadDirEntryErrType); - } - err=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata); - if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) - { - *value=0; - return(err); - } - switch (direntry->tdir_type) - { - case TIFF_DOUBLE: - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong8((uint64*)origdata,count); - TIFFCvtIEEEDoubleToNative(tif,count,(double*)origdata); - *value=(double*)origdata; - return(TIFFReadDirEntryErrOk); - } - data=(double*)_TIFFmalloc(count*sizeof(double)); - if (data==0) - { - _TIFFfree(origdata); - return(TIFFReadDirEntryErrAlloc); - } - switch (direntry->tdir_type) - { - case TIFF_BYTE: - { - uint8* ma; - double* mb; - uint32 n; - ma=(uint8*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort(ma); - *mb++=(double)(*ma++); - } - } - break; - case TIFF_SSHORT: - { - int16* ma; - double* mb; - uint32 n; - ma=(int16*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)ma); - *mb++=(double)(*ma++); - } - } - break; - case TIFF_LONG: - { - uint32* ma; - double* mb; - uint32 n; - ma=(uint32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - *mb++=(double)(*ma++); - } - } - break; - case TIFF_SLONG: - { - int32* ma; - double* mb; - uint32 n; - ma=(int32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)ma); - *mb++=(double)(*ma++); - } - } - break; - case TIFF_LONG8: - { - uint64* ma; - double* mb; - uint32 n; - ma=(uint64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8(ma); + enum TIFFReadDirEntryErr err; + uint32 count; + void* origdata; + double* data; + switch (direntry->tdir_type) + { + case TIFF_BYTE: + case TIFF_SBYTE: + case TIFF_SHORT: + case TIFF_SSHORT: + case TIFF_LONG: + case TIFF_SLONG: + case TIFF_LONG8: + case TIFF_SLONG8: + case TIFF_RATIONAL: + case TIFF_SRATIONAL: + case TIFF_FLOAT: + case TIFF_DOUBLE: + break; + default: + return(TIFFReadDirEntryErrType); + } + err=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata); + if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) + { + *value=0; + return(err); + } + switch (direntry->tdir_type) + { + case TIFF_DOUBLE: + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong8((uint64*)origdata,count); + TIFFCvtIEEEDoubleToNative(tif,count,(double*)origdata); + *value=(double*)origdata; + return(TIFFReadDirEntryErrOk); + } + data=(double*)_TIFFmalloc(count*sizeof(double)); + if (data==0) + { + _TIFFfree(origdata); + return(TIFFReadDirEntryErrAlloc); + } + switch (direntry->tdir_type) + { + case TIFF_BYTE: + { + uint8* ma; + double* mb; + uint32 n; + ma=(uint8*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort(ma); + *mb++=(double)(*ma++); + } + } + break; + case TIFF_SSHORT: + { + int16* ma; + double* mb; + uint32 n; + ma=(int16*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)ma); + *mb++=(double)(*ma++); + } + } + break; + case TIFF_LONG: + { + uint32* ma; + double* mb; + uint32 n; + ma=(uint32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + *mb++=(double)(*ma++); + } + } + break; + case TIFF_SLONG: + { + int32* ma; + double* mb; + uint32 n; + ma=(int32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)ma); + *mb++=(double)(*ma++); + } + } + break; + case TIFF_LONG8: + { + uint64* ma; + double* mb; + uint32 n; + ma=(uint64*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8(ma); #if defined(__WIN32__) && (_MSC_VER < 1500) - /* - * XXX: MSVC 6.0 does not support - * conversion of 64-bit integers into - * floating point values. - */ - *mb++ = _TIFFUInt64ToDouble(*ma++); + /* + * XXX: MSVC 6.0 does not support + * conversion of 64-bit integers into + * floating point values. + */ + *mb++ = _TIFFUInt64ToDouble(*ma++); #else - *mb++ = (double)(*ma++); + *mb++ = (double)(*ma++); #endif - } - } - break; - case TIFF_SLONG8: - { - int64* ma; - double* mb; - uint32 n; - ma=(int64*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)ma); - *mb++=(double)(*ma++); - } - } - break; - case TIFF_RATIONAL: - { - uint32* ma; - uint32 maa; - uint32 mab; - double* mb; - uint32 n; - ma=(uint32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - maa=*ma++; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - mab=*ma++; - if (mab==0) - *mb++=0.0; - else - *mb++=(double)maa/(double)mab; - } - } - break; - case TIFF_SRATIONAL: - { - uint32* ma; - int32 maa; - uint32 mab; - double* mb; - uint32 n; - ma=(uint32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - maa=*(int32*)ma; - ma++; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - mab=*ma++; - if (mab==0) - *mb++=0.0; - else - *mb++=(double)maa/(double)mab; - } - } - break; - case TIFF_FLOAT: - { - float* ma; - double* mb; - uint32 n; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong((uint32*)origdata,count); - TIFFCvtIEEEFloatToNative(tif,count,(float*)origdata); - ma=(float*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)ma); + *mb++=(double)(*ma++); + } + } + break; + case TIFF_RATIONAL: + { + uint32* ma; + uint32 maa; + uint32 mab; + double* mb; + uint32 n; + ma=(uint32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + maa=*ma++; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + mab=*ma++; + if (mab==0) + *mb++=0.0; + else + *mb++=(double)maa/(double)mab; + } + } + break; + case TIFF_SRATIONAL: + { + uint32* ma; + int32 maa; + uint32 mab; + double* mb; + uint32 n; + ma=(uint32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + maa=*(int32*)ma; + ma++; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + mab=*ma++; + if (mab==0) + *mb++=0.0; + else + *mb++=(double)maa/(double)mab; + } + } + break; + case TIFF_FLOAT: + { + float* ma; + double* mb; + uint32 n; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong((uint32*)origdata,count); + TIFFCvtIEEEFloatToNative(tif,count,(float*)origdata); + ma=(float*)origdata; + mb=data; + for (n=0; ntdir_type) - { - case TIFF_LONG: - case TIFF_LONG8: - case TIFF_IFD: - case TIFF_IFD8: - break; - default: - return(TIFFReadDirEntryErrType); - } - err=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata); - if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) - { - *value=0; - return(err); - } - switch (direntry->tdir_type) - { - case TIFF_LONG8: - case TIFF_IFD8: - *value=(uint64*)origdata; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong8(*value,count); - return(TIFFReadDirEntryErrOk); - } - data=(uint64*)_TIFFmalloc(count*8); - if (data==0) - { - _TIFFfree(origdata); - return(TIFFReadDirEntryErrAlloc); - } - switch (direntry->tdir_type) - { - case TIFF_LONG: - case TIFF_IFD: - { - uint32* ma; - uint64* mb; - uint32 n; - ma=(uint32*)origdata; - mb=data; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabLong(ma); - *mb++=(uint64)(*ma++); - } - } - break; - } - _TIFFfree(origdata); - if (err!=TIFFReadDirEntryErrOk) - { - _TIFFfree(data); - return(err); - } - *value=data; - return(TIFFReadDirEntryErrOk); + enum TIFFReadDirEntryErr err; + uint32 count; + void* origdata; + uint64* data; + switch (direntry->tdir_type) + { + case TIFF_LONG: + case TIFF_LONG8: + case TIFF_IFD: + case TIFF_IFD8: + break; + default: + return(TIFFReadDirEntryErrType); + } + err=TIFFReadDirEntryArray(tif,direntry,&count,8,&origdata); + if ((err!=TIFFReadDirEntryErrOk)||(origdata==0)) + { + *value=0; + return(err); + } + switch (direntry->tdir_type) + { + case TIFF_LONG8: + case TIFF_IFD8: + *value=(uint64*)origdata; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong8(*value,count); + return(TIFFReadDirEntryErrOk); + } + data=(uint64*)_TIFFmalloc(count*8); + if (data==0) + { + _TIFFfree(origdata); + return(TIFFReadDirEntryErrAlloc); + } + switch (direntry->tdir_type) + { + case TIFF_LONG: + case TIFF_IFD: + { + uint32* ma; + uint64* mb; + uint32 n; + ma=(uint32*)origdata; + mb=data; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabLong(ma); + *mb++=(uint64)(*ma++); + } + } + break; + } + _TIFFfree(origdata); + *value=data; + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleShort(TIFF* tif, TIFFDirEntry* direntry, uint16* value) { - enum TIFFReadDirEntryErr err; - uint16* m; - uint16* na; - uint16 nb; - if (direntry->tdir_count<(uint64)tif->tif_dir.td_samplesperpixel) - return(TIFFReadDirEntryErrCount); - err=TIFFReadDirEntryShortArray(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - na=m; - nb=tif->tif_dir.td_samplesperpixel; - *value=*na++; - nb--; - while (nb>0) - { - if (*na++!=*value) - { - err=TIFFReadDirEntryErrPsdif; - break; - } - nb--; - } - _TIFFfree(m); - return(err); + enum TIFFReadDirEntryErr err; + uint16* m; + uint16* na; + uint16 nb; + if (direntry->tdir_count<(uint64)tif->tif_dir.td_samplesperpixel) + return(TIFFReadDirEntryErrCount); + err=TIFFReadDirEntryShortArray(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk || m == NULL) + return(err); + na=m; + nb=tif->tif_dir.td_samplesperpixel; + *value=*na++; + nb--; + while (nb>0) + { + if (*na++!=*value) + { + err=TIFFReadDirEntryErrPsdif; + break; + } + nb--; + } + _TIFFfree(m); + return(err); } #if 0 static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleDouble(TIFF* tif, TIFFDirEntry* direntry, double* value) { - enum TIFFReadDirEntryErr err; - double* m; - double* na; - uint16 nb; - if (direntry->tdir_count<(uint64)tif->tif_dir.td_samplesperpixel) - return(TIFFReadDirEntryErrCount); - err=TIFFReadDirEntryDoubleArray(tif,direntry,&m); - if (err!=TIFFReadDirEntryErrOk) - return(err); - na=m; - nb=tif->tif_dir.td_samplesperpixel; - *value=*na++; - nb--; - while (nb>0) - { - if (*na++!=*value) - { - err=TIFFReadDirEntryErrPsdif; - break; - } - nb--; - } - _TIFFfree(m); - return(err); + enum TIFFReadDirEntryErr err; + double* m; + double* na; + uint16 nb; + if (direntry->tdir_count<(uint64)tif->tif_dir.td_samplesperpixel) + return(TIFFReadDirEntryErrCount); + err=TIFFReadDirEntryDoubleArray(tif,direntry,&m); + if (err!=TIFFReadDirEntryErrOk) + return(err); + na=m; + nb=tif->tif_dir.td_samplesperpixel; + *value=*na++; + nb--; + while (nb>0) + { + if (*na++!=*value) + { + err=TIFFReadDirEntryErrPsdif; + break; + } + nb--; + } + _TIFFfree(m); + return(err); } #endif static void TIFFReadDirEntryCheckedByte(TIFF* tif, TIFFDirEntry* direntry, uint8* value) { - (void) tif; - *value=*(uint8*)(&direntry->tdir_offset); + (void) tif; + *value=*(uint8*)(&direntry->tdir_offset); } static void TIFFReadDirEntryCheckedSbyte(TIFF* tif, TIFFDirEntry* direntry, int8* value) { - (void) tif; - *value=*(int8*)(&direntry->tdir_offset); + (void) tif; + *value=*(int8*)(&direntry->tdir_offset); } static void TIFFReadDirEntryCheckedShort(TIFF* tif, TIFFDirEntry* direntry, uint16* value) { - *value = direntry->tdir_offset.toff_short; - /* *value=*(uint16*)(&direntry->tdir_offset); */ - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabShort(value); + *value = direntry->tdir_offset.toff_short; + /* *value=*(uint16*)(&direntry->tdir_offset); */ + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabShort(value); } static void TIFFReadDirEntryCheckedSshort(TIFF* tif, TIFFDirEntry* direntry, int16* value) { - *value=*(int16*)(&direntry->tdir_offset); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)value); + *value=*(int16*)(&direntry->tdir_offset); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)value); } static void TIFFReadDirEntryCheckedLong(TIFF* tif, TIFFDirEntry* direntry, uint32* value) { - *value=*(uint32*)(&direntry->tdir_offset); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(value); + *value=*(uint32*)(&direntry->tdir_offset); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(value); } static void TIFFReadDirEntryCheckedSlong(TIFF* tif, TIFFDirEntry* direntry, int32* value) { - *value=*(int32*)(&direntry->tdir_offset); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)value); + *value=*(int32*)(&direntry->tdir_offset); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)value); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedLong8(TIFF* tif, TIFFDirEntry* direntry, uint64* value) { - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - enum TIFFReadDirEntryErr err; - uint32 offset = direntry->tdir_offset.toff_long; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&offset); - err=TIFFReadDirEntryData(tif,offset,8,value); - if (err!=TIFFReadDirEntryErrOk) - return(err); - } - else - *value = direntry->tdir_offset.toff_long8; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8(value); - return(TIFFReadDirEntryErrOk); + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + enum TIFFReadDirEntryErr err; + uint32 offset = direntry->tdir_offset.toff_long; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&offset); + err=TIFFReadDirEntryData(tif,offset,8,value); + if (err!=TIFFReadDirEntryErrOk) + return(err); + } + else + *value = direntry->tdir_offset.toff_long8; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8(value); + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSlong8(TIFF* tif, TIFFDirEntry* direntry, int64* value) { - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - enum TIFFReadDirEntryErr err; - uint32 offset = direntry->tdir_offset.toff_long; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&offset); - err=TIFFReadDirEntryData(tif,offset,8,value); - if (err!=TIFFReadDirEntryErrOk) - return(err); - } - else - *value=*(int64*)(&direntry->tdir_offset); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)value); - return(TIFFReadDirEntryErrOk); + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + enum TIFFReadDirEntryErr err; + uint32 offset = direntry->tdir_offset.toff_long; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&offset); + err=TIFFReadDirEntryData(tif,offset,8,value); + if (err!=TIFFReadDirEntryErrOk) + return(err); + } + else + *value=*(int64*)(&direntry->tdir_offset); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)value); + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedRational(TIFF* tif, TIFFDirEntry* direntry, double* value) { - UInt64Aligned_t m; + UInt64Aligned_t m; - assert(sizeof(double)==8); - assert(sizeof(uint64)==8); - assert(sizeof(uint32)==4); - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - enum TIFFReadDirEntryErr err; - uint32 offset = direntry->tdir_offset.toff_long; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&offset); - err=TIFFReadDirEntryData(tif,offset,8,m.i); - if (err!=TIFFReadDirEntryErrOk) - return(err); - } - else - m.l = direntry->tdir_offset.toff_long8; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong(m.i,2); - if (m.i[0]==0) - *value=0.0; - else - *value=(double)m.i[0]/(double)m.i[1]; - return(TIFFReadDirEntryErrOk); + assert(sizeof(double)==8); + assert(sizeof(uint64)==8); + assert(sizeof(uint32)==4); + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + enum TIFFReadDirEntryErr err; + uint32 offset = direntry->tdir_offset.toff_long; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&offset); + err=TIFFReadDirEntryData(tif,offset,8,m.i); + if (err!=TIFFReadDirEntryErrOk) + return(err); + } + else + m.l = direntry->tdir_offset.toff_long8; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong(m.i,2); + /* Not completely sure what we should do when m.i[1]==0, but some */ + /* sanitizers do not like division by 0.0: */ + /* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */ + if (m.i[0]==0 || m.i[1]==0) + *value=0.0; + else + *value=(double)m.i[0]/(double)m.i[1]; + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSrational(TIFF* tif, TIFFDirEntry* direntry, double* value) { - UInt64Aligned_t m; - assert(sizeof(double)==8); - assert(sizeof(uint64)==8); - assert(sizeof(int32)==4); - assert(sizeof(uint32)==4); - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - enum TIFFReadDirEntryErr err; - uint32 offset = direntry->tdir_offset.toff_long; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&offset); - err=TIFFReadDirEntryData(tif,offset,8,m.i); - if (err!=TIFFReadDirEntryErrOk) - return(err); - } - else - m.l=direntry->tdir_offset.toff_long8; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong(m.i,2); - if ((int32)m.i[0]==0) - *value=0.0; - else - *value=(double)((int32)m.i[0])/(double)m.i[1]; - return(TIFFReadDirEntryErrOk); + UInt64Aligned_t m; + assert(sizeof(double)==8); + assert(sizeof(uint64)==8); + assert(sizeof(int32)==4); + assert(sizeof(uint32)==4); + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + enum TIFFReadDirEntryErr err; + uint32 offset = direntry->tdir_offset.toff_long; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&offset); + err=TIFFReadDirEntryData(tif,offset,8,m.i); + if (err!=TIFFReadDirEntryErrOk) + return(err); + } + else + m.l=direntry->tdir_offset.toff_long8; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong(m.i,2); + /* Not completely sure what we should do when m.i[1]==0, but some */ + /* sanitizers do not like division by 0.0: */ + /* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */ + if ((int32)m.i[0]==0 || m.i[1]==0) + *value=0.0; + else + *value=(double)((int32)m.i[0])/(double)m.i[1]; + return(TIFFReadDirEntryErrOk); } static void TIFFReadDirEntryCheckedFloat(TIFF* tif, TIFFDirEntry* direntry, float* value) { union - { - float f; - uint32 i; - } float_union; - assert(sizeof(float)==4); - assert(sizeof(uint32)==4); - assert(sizeof(float_union)==4); - float_union.i=*(uint32*)(&direntry->tdir_offset); - *value=float_union.f; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)value); + { + float f; + uint32 i; + } float_union; + assert(sizeof(float)==4); + assert(sizeof(uint32)==4); + assert(sizeof(float_union)==4); + float_union.i=*(uint32*)(&direntry->tdir_offset); + *value=float_union.f; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)value); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedDouble(TIFF* tif, TIFFDirEntry* direntry, double* value) { - assert(sizeof(double)==8); - assert(sizeof(uint64)==8); - assert(sizeof(UInt64Aligned_t)==8); - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - enum TIFFReadDirEntryErr err; - uint32 offset = direntry->tdir_offset.toff_long; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&offset); - err=TIFFReadDirEntryData(tif,offset,8,value); - if (err!=TIFFReadDirEntryErrOk) - return(err); - } - else - { - UInt64Aligned_t uint64_union; - uint64_union.l=direntry->tdir_offset.toff_long8; - *value=uint64_union.d; - } - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)value); - return(TIFFReadDirEntryErrOk); + assert(sizeof(double)==8); + assert(sizeof(uint64)==8); + assert(sizeof(UInt64Aligned_t)==8); + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + enum TIFFReadDirEntryErr err; + uint32 offset = direntry->tdir_offset.toff_long; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&offset); + err=TIFFReadDirEntryData(tif,offset,8,value); + if (err!=TIFFReadDirEntryErrOk) + return(err); + } + else + { + UInt64Aligned_t uint64_union; + uint64_union.l=direntry->tdir_offset.toff_long8; + *value=uint64_union.d; + } + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)value); + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSbyte(int8 value) { - if (value<0) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value<0) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteShort(uint16 value) { - if (value>0xFF) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0xFF) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSshort(int16 value) { - if ((value<0)||(value>0xFF)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value<0)||(value>0xFF)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteLong(uint32 value) { - if (value>0xFF) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0xFF) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSlong(int32 value) { - if ((value<0)||(value>0xFF)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value<0)||(value>0xFF)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteLong8(uint64 value) { - if (value>0xFF) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0xFF) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSlong8(int64 value) { - if ((value<0)||(value>0xFF)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value<0)||(value>0xFF)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteByte(uint8 value) { - if (value>0x7F) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0x7F) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteShort(uint16 value) { - if (value>0x7F) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0x7F) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSshort(int16 value) { - if ((value<-0x80)||(value>0x7F)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value<-0x80)||(value>0x7F)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteLong(uint32 value) { - if (value>0x7F) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0x7F) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSlong(int32 value) { - if ((value<-0x80)||(value>0x7F)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value<-0x80)||(value>0x7F)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteLong8(uint64 value) { - if (value>0x7F) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0x7F) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSlong8(int64 value) { - if ((value<-0x80)||(value>0x7F)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value<-0x80)||(value>0x7F)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSbyte(int8 value) { - if (value<0) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value<0) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSshort(int16 value) { - if (value<0) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value<0) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortLong(uint32 value) { - if (value>0xFFFF) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0xFFFF) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSlong(int32 value) { - if ((value<0)||(value>0xFFFF)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value<0)||(value>0xFFFF)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortLong8(uint64 value) { - if (value>0xFFFF) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0xFFFF) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSlong8(int64 value) { - if ((value<0)||(value>0xFFFF)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value<0)||(value>0xFFFF)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortShort(uint16 value) { - if (value>0x7FFF) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0x7FFF) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortLong(uint32 value) { - if (value>0x7FFF) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0x7FFF) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortSlong(int32 value) { - if ((value<-0x8000)||(value>0x7FFF)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value<-0x8000)||(value>0x7FFF)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortLong8(uint64 value) { - if (value>0x7FFF) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value>0x7FFF) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortSlong8(int64 value) { - if ((value<-0x8000)||(value>0x7FFF)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value<-0x8000)||(value>0x7FFF)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSbyte(int8 value) { - if (value<0) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value<0) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSshort(int16 value) { - if (value<0) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value<0) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSlong(int32 value) { - if (value<0) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value<0) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } /* * Largest 32-bit unsigned integer value. */ -#if defined(__WIN32__) && defined(_MSC_VER) -# define TIFF_UINT32_MAX 0xFFFFFFFFI64 -#else -# define TIFF_UINT32_MAX 0xFFFFFFFFLL -#endif +#define TIFF_UINT32_MAX 0xFFFFFFFFU static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongLong8(uint64 value) { - if (value > TIFF_UINT32_MAX) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value > TIFF_UINT32_MAX) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSlong8(int64 value) { - if ((value<0) || (value > TIFF_UINT32_MAX)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value < 0) || (value > (int64) TIFF_UINT32_MAX)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } #undef TIFF_UINT32_MAX @@ -3223,82 +3316,80 @@ TIFFReadDirEntryCheckRangeLongSlong8(int64 value) static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlongLong(uint32 value) { - if (value > 0x7FFFFFFFUL) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value > 0x7FFFFFFFUL) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } +/* Check that the 8-byte unsigned value can fit in a 4-byte unsigned range */ static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlongLong8(uint64 value) { - if (value > 0x7FFFFFFFUL) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value > 0x7FFFFFFF) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } +/* Check that the 8-byte signed value can fit in a 4-byte signed range */ static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlongSlong8(int64 value) { - if ((value < 0L-0x80000000L) || (value > 0x7FFFFFFFL)) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if ((value < 0-((int64) 0x7FFFFFFF+1)) || (value > 0x7FFFFFFF)) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Sbyte(int8 value) { - if (value < 0) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value < 0) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Sshort(int16 value) { - if (value < 0) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value < 0) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Slong(int32 value) { - if (value < 0) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value < 0) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Slong8(int64 value) { - if (value < 0) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value < 0) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } /* * Largest 64-bit signed integer value. */ -#if defined(__WIN32__) && defined(_MSC_VER) -# define TIFF_INT64_MAX 0x7FFFFFFFFFFFFFFFI64 -#else -# define TIFF_INT64_MAX 0x7FFFFFFFFFFFFFFFLL -#endif +#define TIFF_INT64_MAX ((int64)(((uint64) ~0) >> 1)) static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlong8Long8(uint64 value) { - if (value > TIFF_INT64_MAX) - return(TIFFReadDirEntryErrRange); - else - return(TIFFReadDirEntryErrOk); + if (value > TIFF_INT64_MAX) + return(TIFFReadDirEntryErrRange); + else + return(TIFFReadDirEntryErrOk); } #undef TIFF_INT64_MAX @@ -3306,108 +3397,113 @@ TIFFReadDirEntryCheckRangeSlong8Long8(uint64 value) static enum TIFFReadDirEntryErr TIFFReadDirEntryData(TIFF* tif, uint64 offset, tmsize_t size, void* dest) { - assert(size>0); - if (!isMapped(tif)) { - if (!SeekOK(tif,offset)) - return(TIFFReadDirEntryErrIo); - if (!ReadOK(tif,dest,size)) - return(TIFFReadDirEntryErrIo); - } else { - tmsize_t ma,mb; - ma=(tmsize_t)offset; - mb=ma+size; - if (((uint64)ma!=offset)||(mbtif->tif_size)) - return(TIFFReadDirEntryErrIo); - _TIFFmemcpy(dest,tif->tif_base+ma,size); - } - return(TIFFReadDirEntryErrOk); + assert(size>0); + if (!isMapped(tif)) { + if (!SeekOK(tif,offset)) + return(TIFFReadDirEntryErrIo); + if (!ReadOK(tif,dest,size)) + return(TIFFReadDirEntryErrIo); + } else { + size_t ma,mb; + ma=(size_t)offset; + mb=ma+size; + if (((uint64)ma!=offset) + || (mb < ma) + || (mb - ma != (size_t) size) + || (mb < (size_t)size) + || (mb > (size_t)tif->tif_size) + ) + return(TIFFReadDirEntryErrIo); + _TIFFmemcpy(dest,tif->tif_base+ma,size); + } + return(TIFFReadDirEntryErrOk); } static void TIFFReadDirEntryOutputErr(TIFF* tif, enum TIFFReadDirEntryErr err, const char* module, const char* tagname, int recover) { - if (!recover) { - switch (err) { - case TIFFReadDirEntryErrCount: - TIFFErrorExt(tif->tif_clientdata, module, - "Incorrect count for \"%s\"", - tagname); - break; - case TIFFReadDirEntryErrType: - TIFFErrorExt(tif->tif_clientdata, module, - "Incompatible type for \"%s\"", - tagname); - break; - case TIFFReadDirEntryErrIo: - TIFFErrorExt(tif->tif_clientdata, module, - "IO error during reading of \"%s\"", - tagname); - break; - case TIFFReadDirEntryErrRange: - TIFFErrorExt(tif->tif_clientdata, module, - "Incorrect value for \"%s\"", - tagname); - break; - case TIFFReadDirEntryErrPsdif: - TIFFErrorExt(tif->tif_clientdata, module, - "Cannot handle different values per sample for \"%s\"", - tagname); - break; - case TIFFReadDirEntryErrSizesan: - TIFFErrorExt(tif->tif_clientdata, module, - "Sanity check on size of \"%s\" value failed", - tagname); - break; - case TIFFReadDirEntryErrAlloc: - TIFFErrorExt(tif->tif_clientdata, module, - "Out of memory reading of \"%s\"", - tagname); - break; - default: - assert(0); /* we should never get here */ - break; - } - } else { - switch (err) { - case TIFFReadDirEntryErrCount: - TIFFErrorExt(tif->tif_clientdata, module, - "Incorrect count for \"%s\"; tag ignored", - tagname); - break; - case TIFFReadDirEntryErrType: - TIFFWarningExt(tif->tif_clientdata, module, - "Incompatible type for \"%s\"; tag ignored", - tagname); - break; - case TIFFReadDirEntryErrIo: - TIFFWarningExt(tif->tif_clientdata, module, - "IO error during reading of \"%s\"; tag ignored", - tagname); - break; - case TIFFReadDirEntryErrRange: - TIFFWarningExt(tif->tif_clientdata, module, - "Incorrect value for \"%s\"; tag ignored", - tagname); - break; - case TIFFReadDirEntryErrPsdif: - TIFFWarningExt(tif->tif_clientdata, module, - "Cannot handle different values per sample for \"%s\"; tag ignored", - tagname); - break; - case TIFFReadDirEntryErrSizesan: - TIFFWarningExt(tif->tif_clientdata, module, - "Sanity check on size of \"%s\" value failed; tag ignored", - tagname); - break; - case TIFFReadDirEntryErrAlloc: - TIFFWarningExt(tif->tif_clientdata, module, - "Out of memory reading of \"%s\"; tag ignored", - tagname); - break; - default: - assert(0); /* we should never get here */ - break; - } - } + if (!recover) { + switch (err) { + case TIFFReadDirEntryErrCount: + TIFFErrorExt(tif->tif_clientdata, module, + "Incorrect count for \"%s\"", + tagname); + break; + case TIFFReadDirEntryErrType: + TIFFErrorExt(tif->tif_clientdata, module, + "Incompatible type for \"%s\"", + tagname); + break; + case TIFFReadDirEntryErrIo: + TIFFErrorExt(tif->tif_clientdata, module, + "IO error during reading of \"%s\"", + tagname); + break; + case TIFFReadDirEntryErrRange: + TIFFErrorExt(tif->tif_clientdata, module, + "Incorrect value for \"%s\"", + tagname); + break; + case TIFFReadDirEntryErrPsdif: + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot handle different values per sample for \"%s\"", + tagname); + break; + case TIFFReadDirEntryErrSizesan: + TIFFErrorExt(tif->tif_clientdata, module, + "Sanity check on size of \"%s\" value failed", + tagname); + break; + case TIFFReadDirEntryErrAlloc: + TIFFErrorExt(tif->tif_clientdata, module, + "Out of memory reading of \"%s\"", + tagname); + break; + default: + assert(0); /* we should never get here */ + break; + } + } else { + switch (err) { + case TIFFReadDirEntryErrCount: + TIFFWarningExt(tif->tif_clientdata, module, + "Incorrect count for \"%s\"; tag ignored", + tagname); + break; + case TIFFReadDirEntryErrType: + TIFFWarningExt(tif->tif_clientdata, module, + "Incompatible type for \"%s\"; tag ignored", + tagname); + break; + case TIFFReadDirEntryErrIo: + TIFFWarningExt(tif->tif_clientdata, module, + "IO error during reading of \"%s\"; tag ignored", + tagname); + break; + case TIFFReadDirEntryErrRange: + TIFFWarningExt(tif->tif_clientdata, module, + "Incorrect value for \"%s\"; tag ignored", + tagname); + break; + case TIFFReadDirEntryErrPsdif: + TIFFWarningExt(tif->tif_clientdata, module, + "Cannot handle different values per sample for \"%s\"; tag ignored", + tagname); + break; + case TIFFReadDirEntryErrSizesan: + TIFFWarningExt(tif->tif_clientdata, module, + "Sanity check on size of \"%s\" value failed; tag ignored", + tagname); + break; + case TIFFReadDirEntryErrAlloc: + TIFFWarningExt(tif->tif_clientdata, module, + "Out of memory reading of \"%s\"; tag ignored", + tagname); + break; + default: + assert(0); /* we should never get here */ + break; + } + } } /* @@ -3417,839 +3513,893 @@ static void TIFFReadDirEntryOutputErr(TIFF* tif, enum TIFFReadDirEntryErr err, c int TIFFReadDirectory(TIFF* tif) { - static const char module[] = "TIFFReadDirectory"; - TIFFDirEntry* dir; - uint16 dircount; - TIFFDirEntry* dp; - uint16 di; - const TIFFField* fip; - uint32 fii=FAILED_FII; + static const char module[] = "TIFFReadDirectory"; + TIFFDirEntry* dir; + uint16 dircount; + TIFFDirEntry* dp; + uint16 di; + const TIFFField* fip; + uint32 fii=FAILED_FII; toff_t nextdiroff; - tif->tif_diroff=tif->tif_nextdiroff; - if (!TIFFCheckDirOffset(tif,tif->tif_nextdiroff)) - return 0; /* last offset or bad offset (IFD looping) */ - (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */ - tif->tif_curdir++; + int bitspersample_read = FALSE; + + tif->tif_diroff=tif->tif_nextdiroff; + if (!TIFFCheckDirOffset(tif,tif->tif_nextdiroff)) + return 0; /* last offset or bad offset (IFD looping) */ + (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */ + tif->tif_curdir++; nextdiroff = tif->tif_nextdiroff; - dircount=TIFFFetchDirectory(tif,nextdiroff,&dir,&tif->tif_nextdiroff); - if (!dircount) - { - TIFFErrorExt(tif->tif_clientdata,module, - "Failed to read directory at offset " TIFF_UINT64_FORMAT,nextdiroff); - return 0; - } - TIFFReadDirectoryCheckOrder(tif,dir,dircount); + dircount=TIFFFetchDirectory(tif,nextdiroff,&dir,&tif->tif_nextdiroff); + if (!dircount) + { + TIFFErrorExt(tif->tif_clientdata,module, + "Failed to read directory at offset " TIFF_UINT64_FORMAT,nextdiroff); + return 0; + } + TIFFReadDirectoryCheckOrder(tif,dir,dircount); /* * Mark duplicates of any tag to be ignored (bugzilla 1994) * to avoid certain pathological problems. */ - { - TIFFDirEntry* ma; - uint16 mb; - for (ma=dir, mb=0; mbtdir_tag==na->tdir_tag) - na->tdir_tag=IGNORE; - } - } - } - - tif->tif_flags &= ~TIFF_BEENWRITING; /* reset before new dir */ - tif->tif_flags &= ~TIFF_BUF4WRITE; /* reset before new dir */ - /* free any old stuff and reinit */ - TIFFFreeDirectory(tif); - TIFFDefaultDirectory(tif); - /* - * Electronic Arts writes gray-scale TIFF files - * without a PlanarConfiguration directory entry. - * Thus we setup a default value here, even though - * the TIFF spec says there is no default value. - */ - TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); - /* - * Setup default value and then make a pass over - * the fields to check type and tag information, - * and to extract info required to size data - * structures. A second pass is made afterwards - * to read in everthing not taken in the first pass. - * But we must process the Compression tag first - * in order to merge in codec-private tag definitions (otherwise - * we may get complaints about unknown tags). However, the - * Compression tag may be dependent on the SamplesPerPixel - * tag value because older TIFF specs permited Compression - * to be written as a SamplesPerPixel-count tag entry. - * Thus if we don't first figure out the correct SamplesPerPixel - * tag value then we may end up ignoring the Compression tag - * value because it has an incorrect count value (if the - * true value of SamplesPerPixel is not 1). - */ - dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_SAMPLESPERPIXEL); - if (dp) - { - if (!TIFFFetchNormalTag(tif,dp,0)) - goto bad; - dp->tdir_tag=IGNORE; - } - dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_COMPRESSION); - if (dp) - { - /* - * The 5.0 spec says the Compression tag has one value, while - * earlier specs say it has one value per sample. Because of - * this, we accept the tag if one value is supplied with either - * count. - */ - uint16 value; - enum TIFFReadDirEntryErr err; - err=TIFFReadDirEntryShort(tif,dp,&value); - if (err==TIFFReadDirEntryErrCount) - err=TIFFReadDirEntryPersampleShort(tif,dp,&value); - if (err!=TIFFReadDirEntryErrOk) - { - TIFFReadDirEntryOutputErr(tif,err,module,"Compression",0); - goto bad; - } - if (!TIFFSetField(tif,TIFFTAG_COMPRESSION,value)) - goto bad; - dp->tdir_tag=IGNORE; - } - else - { - if (!TIFFSetField(tif,TIFFTAG_COMPRESSION,COMPRESSION_NONE)) - goto bad; - } - /* - * First real pass over the directory. - */ - for (di=0, dp=dir; ditdir_tag!=IGNORE) - { - TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); - if (fii == FAILED_FII) - { - TIFFWarningExt(tif->tif_clientdata, module, - "Unknown field with tag %d (0x%x) encountered", - dp->tdir_tag,dp->tdir_tag); - /* the following knowingly leaks the + { + TIFFDirEntry* ma; + uint16 mb; + for (ma=dir, mb=0; mbtdir_tag==na->tdir_tag) + na->tdir_tag=IGNORE; + } + } + } + + tif->tif_flags &= ~TIFF_BEENWRITING; /* reset before new dir */ + tif->tif_flags &= ~TIFF_BUF4WRITE; /* reset before new dir */ + /* free any old stuff and reinit */ + TIFFFreeDirectory(tif); + TIFFDefaultDirectory(tif); + /* + * Electronic Arts writes gray-scale TIFF files + * without a PlanarConfiguration directory entry. + * Thus we setup a default value here, even though + * the TIFF spec says there is no default value. + */ + TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG); + /* + * Setup default value and then make a pass over + * the fields to check type and tag information, + * and to extract info required to size data + * structures. A second pass is made afterwards + * to read in everything not taken in the first pass. + * But we must process the Compression tag first + * in order to merge in codec-private tag definitions (otherwise + * we may get complaints about unknown tags). However, the + * Compression tag may be dependent on the SamplesPerPixel + * tag value because older TIFF specs permitted Compression + * to be written as a SamplesPerPixel-count tag entry. + * Thus if we don't first figure out the correct SamplesPerPixel + * tag value then we may end up ignoring the Compression tag + * value because it has an incorrect count value (if the + * true value of SamplesPerPixel is not 1). + */ + dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_SAMPLESPERPIXEL); + if (dp) + { + if (!TIFFFetchNormalTag(tif,dp,0)) + goto bad; + dp->tdir_tag=IGNORE; + } + dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_COMPRESSION); + if (dp) + { + /* + * The 5.0 spec says the Compression tag has one value, while + * earlier specs say it has one value per sample. Because of + * this, we accept the tag if one value is supplied with either + * count. + */ + uint16 value; + enum TIFFReadDirEntryErr err; + err=TIFFReadDirEntryShort(tif,dp,&value); + if (err==TIFFReadDirEntryErrCount) + err=TIFFReadDirEntryPersampleShort(tif,dp,&value); + if (err!=TIFFReadDirEntryErrOk) + { + TIFFReadDirEntryOutputErr(tif,err,module,"Compression",0); + goto bad; + } + if (!TIFFSetField(tif,TIFFTAG_COMPRESSION,value)) + goto bad; + dp->tdir_tag=IGNORE; + } + else + { + if (!TIFFSetField(tif,TIFFTAG_COMPRESSION,COMPRESSION_NONE)) + goto bad; + } + /* + * First real pass over the directory. + */ + for (di=0, dp=dir; ditdir_tag!=IGNORE) + { + TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); + if (fii == FAILED_FII) + { + TIFFWarningExt(tif->tif_clientdata, module, + "Unknown field with tag %d (0x%x) encountered", + dp->tdir_tag,dp->tdir_tag); + /* the following knowingly leaks the anonymous field structure */ - if (!_TIFFMergeFields(tif, - _TIFFCreateAnonField(tif, - dp->tdir_tag, - (TIFFDataType) dp->tdir_type), - 1)) { - TIFFWarningExt(tif->tif_clientdata, - module, - "Registering anonymous field with tag %d (0x%x) failed", - dp->tdir_tag, - dp->tdir_tag); - dp->tdir_tag=IGNORE; - } else { - TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); - assert(fii != FAILED_FII); - } - } - } - if (dp->tdir_tag!=IGNORE) - { - fip=tif->tif_fields[fii]; - if (fip->field_bit==FIELD_IGNORE) - dp->tdir_tag=IGNORE; - else - { - switch (dp->tdir_tag) - { - case TIFFTAG_STRIPOFFSETS: - case TIFFTAG_STRIPBYTECOUNTS: - case TIFFTAG_TILEOFFSETS: - case TIFFTAG_TILEBYTECOUNTS: - TIFFSetFieldBit(tif,fip->field_bit); - break; - case TIFFTAG_IMAGEWIDTH: - case TIFFTAG_IMAGELENGTH: - case TIFFTAG_IMAGEDEPTH: - case TIFFTAG_TILELENGTH: - case TIFFTAG_TILEWIDTH: - case TIFFTAG_TILEDEPTH: - case TIFFTAG_PLANARCONFIG: - case TIFFTAG_ROWSPERSTRIP: - case TIFFTAG_EXTRASAMPLES: - if (!TIFFFetchNormalTag(tif,dp,0)) - goto bad; - dp->tdir_tag=IGNORE; - break; - } - } - } - } - /* - * XXX: OJPEG hack. - * If a) compression is OJPEG, b) planarconfig tag says it's separate, - * c) strip offsets/bytecounts tag are both present and - * d) both contain exactly one value, then we consistently find - * that the buggy implementation of the buggy compression scheme - * matches contig planarconfig best. So we 'fix-up' the tag here - */ - if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG)&& - (tif->tif_dir.td_planarconfig==PLANARCONFIG_SEPARATE)) - { + if (!_TIFFMergeFields(tif, + _TIFFCreateAnonField(tif, + dp->tdir_tag, + (TIFFDataType) dp->tdir_type), + 1)) { + TIFFWarningExt(tif->tif_clientdata, + module, + "Registering anonymous field with tag %d (0x%x) failed", + dp->tdir_tag, + dp->tdir_tag); + dp->tdir_tag=IGNORE; + } else { + TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); + assert(fii != FAILED_FII); + } + } + } + if (dp->tdir_tag!=IGNORE) + { + fip=tif->tif_fields[fii]; + if (fip->field_bit==FIELD_IGNORE) + dp->tdir_tag=IGNORE; + else + { + switch (dp->tdir_tag) + { + case TIFFTAG_STRIPOFFSETS: + case TIFFTAG_STRIPBYTECOUNTS: + case TIFFTAG_TILEOFFSETS: + case TIFFTAG_TILEBYTECOUNTS: + TIFFSetFieldBit(tif,fip->field_bit); + break; + case TIFFTAG_IMAGEWIDTH: + case TIFFTAG_IMAGELENGTH: + case TIFFTAG_IMAGEDEPTH: + case TIFFTAG_TILELENGTH: + case TIFFTAG_TILEWIDTH: + case TIFFTAG_TILEDEPTH: + case TIFFTAG_PLANARCONFIG: + case TIFFTAG_ROWSPERSTRIP: + case TIFFTAG_EXTRASAMPLES: + if (!TIFFFetchNormalTag(tif,dp,0)) + goto bad; + dp->tdir_tag=IGNORE; + break; + default: + if( !_TIFFCheckFieldIsValidForCodec(tif, dp->tdir_tag) ) + dp->tdir_tag=IGNORE; + break; + } + } + } + } + /* + * XXX: OJPEG hack. + * If a) compression is OJPEG, b) planarconfig tag says it's separate, + * c) strip offsets/bytecounts tag are both present and + * d) both contain exactly one value, then we consistently find + * that the buggy implementation of the buggy compression scheme + * matches contig planarconfig best. So we 'fix-up' the tag here + */ + if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG)&& + (tif->tif_dir.td_planarconfig==PLANARCONFIG_SEPARATE)) + { if (!_TIFFFillStriles(tif)) goto bad; - dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_STRIPOFFSETS); - if ((dp!=0)&&(dp->tdir_count==1)) + dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_STRIPOFFSETS); + if ((dp!=0)&&(dp->tdir_count==1)) + { + dp=TIFFReadDirectoryFindEntry(tif,dir,dircount, + TIFFTAG_STRIPBYTECOUNTS); + if ((dp!=0)&&(dp->tdir_count==1)) + { + tif->tif_dir.td_planarconfig=PLANARCONFIG_CONTIG; + TIFFWarningExt(tif->tif_clientdata,module, + "Planarconfig tag value assumed incorrect, " + "assuming data is contig instead of chunky"); + } + } + } + /* + * Allocate directory structure and setup defaults. + */ + if (!TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) + { + MissingRequired(tif,"ImageLength"); + goto bad; + } + /* + * Setup appropriate structures (by strip or by tile) + */ + if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { + tif->tif_dir.td_nstrips = TIFFNumberOfStrips(tif); + tif->tif_dir.td_tilewidth = tif->tif_dir.td_imagewidth; + tif->tif_dir.td_tilelength = tif->tif_dir.td_rowsperstrip; + tif->tif_dir.td_tiledepth = tif->tif_dir.td_imagedepth; + tif->tif_flags &= ~TIFF_ISTILED; + } else { + tif->tif_dir.td_nstrips = TIFFNumberOfTiles(tif); + tif->tif_flags |= TIFF_ISTILED; + } + if (!tif->tif_dir.td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot handle zero number of %s", + isTiled(tif) ? "tiles" : "strips"); + goto bad; + } + tif->tif_dir.td_stripsperimage = tif->tif_dir.td_nstrips; + if (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE) + tif->tif_dir.td_stripsperimage /= tif->tif_dir.td_samplesperpixel; + if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) { +#ifdef OJPEG_SUPPORT + if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG) && + (isTiled(tif)==0) && + (tif->tif_dir.td_nstrips==1)) { + /* + * XXX: OJPEG hack. + * If a) compression is OJPEG, b) it's not a tiled TIFF, + * and c) the number of strips is 1, + * then we tolerate the absence of stripoffsets tag, + * because, presumably, all required data is in the + * JpegInterchangeFormat stream. + */ + TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); + } else +#endif { - dp=TIFFReadDirectoryFindEntry(tif,dir,dircount, - TIFFTAG_STRIPBYTECOUNTS); - if ((dp!=0)&&(dp->tdir_count==1)) - { - tif->tif_dir.td_planarconfig=PLANARCONFIG_CONTIG; - TIFFWarningExt(tif->tif_clientdata,module, - "Planarconfig tag value assumed incorrect, " - "assuming data is contig instead of chunky"); - } - } - } - /* - * Allocate directory structure and setup defaults. - */ - if (!TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) - { - MissingRequired(tif,"ImageLength"); - goto bad; - } - /* - * Setup appropriate structures (by strip or by tile) - */ - if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { - tif->tif_dir.td_nstrips = TIFFNumberOfStrips(tif); - tif->tif_dir.td_tilewidth = tif->tif_dir.td_imagewidth; - tif->tif_dir.td_tilelength = tif->tif_dir.td_rowsperstrip; - tif->tif_dir.td_tiledepth = tif->tif_dir.td_imagedepth; - tif->tif_flags &= ~TIFF_ISTILED; - } else { - tif->tif_dir.td_nstrips = TIFFNumberOfTiles(tif); - tif->tif_flags |= TIFF_ISTILED; - } - if (!tif->tif_dir.td_nstrips) { - TIFFErrorExt(tif->tif_clientdata, module, - "Cannot handle zero number of %s", - isTiled(tif) ? "tiles" : "strips"); - goto bad; - } - tif->tif_dir.td_stripsperimage = tif->tif_dir.td_nstrips; - if (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE) - tif->tif_dir.td_stripsperimage /= tif->tif_dir.td_samplesperpixel; - if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) { - if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG) && - (isTiled(tif)==0) && - (tif->tif_dir.td_nstrips==1)) { - /* - * XXX: OJPEG hack. - * If a) compression is OJPEG, b) it's not a tiled TIFF, - * and c) the number of strips is 1, - * then we tolerate the absence of stripoffsets tag, - * because, presumably, all required data is in the - * JpegInterchangeFormat stream. - */ - TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); - } else { - MissingRequired(tif, - isTiled(tif) ? "TileOffsets" : "StripOffsets"); - goto bad; - } - } - /* - * Second pass: extract other information. - */ - for (di=0, dp=dir; ditdir_tag) - { - case IGNORE: - break; - case TIFFTAG_MINSAMPLEVALUE: - case TIFFTAG_MAXSAMPLEVALUE: - case TIFFTAG_BITSPERSAMPLE: - case TIFFTAG_DATATYPE: - case TIFFTAG_SAMPLEFORMAT: - /* - * The MinSampleValue, MaxSampleValue, BitsPerSample - * DataType and SampleFormat tags are supposed to be - * written as one value/sample, but some vendors - * incorrectly write one value only -- so we accept - * that as well (yech). Other vendors write correct - * value for NumberOfSamples, but incorrect one for - * BitsPerSample and friends, and we will read this - * too. - */ - { - uint16 value; - enum TIFFReadDirEntryErr err; - err=TIFFReadDirEntryShort(tif,dp,&value); - if (err==TIFFReadDirEntryErrCount) - err=TIFFReadDirEntryPersampleShort(tif,dp,&value); - if (err!=TIFFReadDirEntryErrOk) - { - fip = TIFFFieldWithTag(tif,dp->tdir_tag); - TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); - goto bad; - } - if (!TIFFSetField(tif,dp->tdir_tag,value)) - goto bad; - } - break; - case TIFFTAG_SMINSAMPLEVALUE: - case TIFFTAG_SMAXSAMPLEVALUE: - { + MissingRequired(tif, + isTiled(tif) ? "TileOffsets" : "StripOffsets"); + goto bad; + } + } + /* + * Second pass: extract other information. + */ + for (di=0, dp=dir; ditdir_tag) + { + case IGNORE: + break; + case TIFFTAG_MINSAMPLEVALUE: + case TIFFTAG_MAXSAMPLEVALUE: + case TIFFTAG_BITSPERSAMPLE: + case TIFFTAG_DATATYPE: + case TIFFTAG_SAMPLEFORMAT: + /* + * The MinSampleValue, MaxSampleValue, BitsPerSample + * DataType and SampleFormat tags are supposed to be + * written as one value/sample, but some vendors + * incorrectly write one value only -- so we accept + * that as well (yuck). Other vendors write correct + * value for NumberOfSamples, but incorrect one for + * BitsPerSample and friends, and we will read this + * too. + */ + { + uint16 value; + enum TIFFReadDirEntryErr err; + err=TIFFReadDirEntryShort(tif,dp,&value); + if (err==TIFFReadDirEntryErrCount) + err=TIFFReadDirEntryPersampleShort(tif,dp,&value); + if (err!=TIFFReadDirEntryErrOk) + { + fip = TIFFFieldWithTag(tif,dp->tdir_tag); + TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); + goto bad; + } + if (!TIFFSetField(tif,dp->tdir_tag,value)) + goto bad; + if( dp->tdir_tag == TIFFTAG_BITSPERSAMPLE ) + bitspersample_read = TRUE; + } + break; + case TIFFTAG_SMINSAMPLEVALUE: + case TIFFTAG_SMAXSAMPLEVALUE: + { - double *data = 0; - enum TIFFReadDirEntryErr err; - uint32 saved_flags; - int m; - if (dp->tdir_count != (uint64)tif->tif_dir.td_samplesperpixel) - err = TIFFReadDirEntryErrCount; - else - err = TIFFReadDirEntryDoubleArray(tif, dp, &data); - if (err!=TIFFReadDirEntryErrOk) - { - fip = TIFFFieldWithTag(tif,dp->tdir_tag); - TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); - goto bad; - } - saved_flags = tif->tif_flags; - tif->tif_flags |= TIFF_PERSAMPLE; - m = TIFFSetField(tif,dp->tdir_tag,data); - tif->tif_flags = saved_flags; - _TIFFfree(data); - if (!m) - goto bad; - } - break; - case TIFFTAG_STRIPOFFSETS: - case TIFFTAG_TILEOFFSETS: + double *data = NULL; + enum TIFFReadDirEntryErr err; + uint32 saved_flags; + int m; + if (dp->tdir_count != (uint64)tif->tif_dir.td_samplesperpixel) + err = TIFFReadDirEntryErrCount; + else + err = TIFFReadDirEntryDoubleArray(tif, dp, &data); + if (err!=TIFFReadDirEntryErrOk) + { + fip = TIFFFieldWithTag(tif,dp->tdir_tag); + TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); + goto bad; + } + saved_flags = tif->tif_flags; + tif->tif_flags |= TIFF_PERSAMPLE; + m = TIFFSetField(tif,dp->tdir_tag,data); + tif->tif_flags = saved_flags; + _TIFFfree(data); + if (!m) + goto bad; + } + break; + case TIFFTAG_STRIPOFFSETS: + case TIFFTAG_TILEOFFSETS: #if defined(DEFER_STRILE_LOAD) _TIFFmemcpy( &(tif->tif_dir.td_stripoffset_entry), dp, sizeof(TIFFDirEntry) ); -#else - if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripoffset)) - goto bad; -#endif - break; - case TIFFTAG_STRIPBYTECOUNTS: - case TIFFTAG_TILEBYTECOUNTS: +#else + if( tif->tif_dir.td_stripoffset != NULL ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "tif->tif_dir.td_stripoffset is " + "already allocated. Likely duplicated " + "StripOffsets/TileOffsets tag"); + goto bad; + } + if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripoffset)) + goto bad; +#endif + break; + case TIFFTAG_STRIPBYTECOUNTS: + case TIFFTAG_TILEBYTECOUNTS: #if defined(DEFER_STRILE_LOAD) _TIFFmemcpy( &(tif->tif_dir.td_stripbytecount_entry), dp, sizeof(TIFFDirEntry) ); -#else - if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripbytecount)) - goto bad; -#endif - break; - case TIFFTAG_COLORMAP: - case TIFFTAG_TRANSFERFUNCTION: - { - enum TIFFReadDirEntryErr err; - uint32 countpersample; - uint32 countrequired; - uint32 incrementpersample; - uint16* value=NULL; - countpersample=(1L<tif_dir.td_bitspersample); - if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample)) - { - countrequired=countpersample; - incrementpersample=0; - } - else - { - countrequired=3*countpersample; - incrementpersample=countpersample; - } - if (dp->tdir_count!=(uint64)countrequired) - err=TIFFReadDirEntryErrCount; - else - err=TIFFReadDirEntryShortArray(tif,dp,&value); - if (err!=TIFFReadDirEntryErrOk) +#else + if( tif->tif_dir.td_stripbytecount != NULL ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "tif->tif_dir.td_stripbytecount is " + "already allocated. Likely duplicated " + "StripByteCounts/TileByteCounts tag"); + goto bad; + } + if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripbytecount)) + goto bad; +#endif + break; + case TIFFTAG_COLORMAP: + case TIFFTAG_TRANSFERFUNCTION: + { + enum TIFFReadDirEntryErr err; + uint32 countpersample; + uint32 countrequired; + uint32 incrementpersample; + uint16* value=NULL; + /* It would be dangerous to instantiate those tag values */ + /* since if td_bitspersample has not yet been read (due to */ + /* unordered tags), it could be read afterwards with a */ + /* values greater than the default one (1), which may cause */ + /* crashes in user code */ + if( !bitspersample_read ) { fip = TIFFFieldWithTag(tif,dp->tdir_tag); - TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",1); + TIFFWarningExt(tif->tif_clientdata,module, + "Ignoring %s since BitsPerSample tag not found", + fip ? fip->field_name : "unknown tagname"); + continue; } - else + /* ColorMap or TransferFunction for high bit */ + /* depths do not make much sense and could be */ + /* used as a denial of service vector */ + if (tif->tif_dir.td_bitspersample > 24) + { + fip = TIFFFieldWithTag(tif,dp->tdir_tag); + TIFFWarningExt(tif->tif_clientdata,module, + "Ignoring %s because BitsPerSample=%d>24", + fip ? fip->field_name : "unknown tagname", + tif->tif_dir.td_bitspersample); + continue; + } + countpersample=(1U<tif_dir.td_bitspersample); + if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample)) + { + countrequired=countpersample; + incrementpersample=0; + } + else + { + countrequired=3*countpersample; + incrementpersample=countpersample; + } + if (dp->tdir_count!=(uint64)countrequired) + err=TIFFReadDirEntryErrCount; + else + err=TIFFReadDirEntryShortArray(tif,dp,&value); + if (err!=TIFFReadDirEntryErrOk) { - TIFFSetField(tif,dp->tdir_tag,value,value+incrementpersample,value+2*incrementpersample); - _TIFFfree(value); + fip = TIFFFieldWithTag(tif,dp->tdir_tag); + TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",1); } - } - break; + else + { + TIFFSetField(tif,dp->tdir_tag,value,value+incrementpersample,value+2*incrementpersample); + _TIFFfree(value); + } + } + break; /* BEGIN REV 4.0 COMPATIBILITY */ - case TIFFTAG_OSUBFILETYPE: - { - uint16 valueo; - uint32 value; - if (TIFFReadDirEntryShort(tif,dp,&valueo)==TIFFReadDirEntryErrOk) - { - switch (valueo) - { - case OFILETYPE_REDUCEDIMAGE: value=FILETYPE_REDUCEDIMAGE; break; - case OFILETYPE_PAGE: value=FILETYPE_PAGE; break; - default: value=0; break; - } - if (value!=0) - TIFFSetField(tif,TIFFTAG_SUBFILETYPE,value); - } - } - break; + case TIFFTAG_OSUBFILETYPE: + { + uint16 valueo; + uint32 value; + if (TIFFReadDirEntryShort(tif,dp,&valueo)==TIFFReadDirEntryErrOk) + { + switch (valueo) + { + case OFILETYPE_REDUCEDIMAGE: value=FILETYPE_REDUCEDIMAGE; break; + case OFILETYPE_PAGE: value=FILETYPE_PAGE; break; + default: value=0; break; + } + if (value!=0) + TIFFSetField(tif,TIFFTAG_SUBFILETYPE,value); + } + } + break; /* END REV 4.0 COMPATIBILITY */ - default: - (void) TIFFFetchNormalTag(tif, dp, TRUE); - break; - } - } - /* - * OJPEG hack: - * - If a) compression is OJPEG, and b) photometric tag is missing, - * then we consistently find that photometric should be YCbCr - * - If a) compression is OJPEG, and b) photometric tag says it's RGB, - * then we consistently find that the buggy implementation of the - * buggy compression scheme matches photometric YCbCr instead. - * - If a) compression is OJPEG, and b) bitspersample tag is missing, - * then we consistently find bitspersample should be 8. - * - If a) compression is OJPEG, b) samplesperpixel tag is missing, - * and c) photometric is RGB or YCbCr, then we consistently find - * samplesperpixel should be 3 - * - If a) compression is OJPEG, b) samplesperpixel tag is missing, - * and c) photometric is MINISWHITE or MINISBLACK, then we consistently - * find samplesperpixel should be 3 - */ - if (tif->tif_dir.td_compression==COMPRESSION_OJPEG) - { - if (!TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) - { - TIFFWarningExt(tif->tif_clientdata, module, - "Photometric tag is missing, assuming data is YCbCr"); - if (!TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_YCBCR)) - goto bad; - } - else if (tif->tif_dir.td_photometric==PHOTOMETRIC_RGB) - { - tif->tif_dir.td_photometric=PHOTOMETRIC_YCBCR; - TIFFWarningExt(tif->tif_clientdata, module, - "Photometric tag value assumed incorrect, " - "assuming data is YCbCr instead of RGB"); - } - if (!TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) - { - TIFFWarningExt(tif->tif_clientdata,module, - "BitsPerSample tag is missing, assuming 8 bits per sample"); - if (!TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,8)) - goto bad; - } - if (!TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) - { - if (tif->tif_dir.td_photometric==PHOTOMETRIC_RGB) - { - TIFFWarningExt(tif->tif_clientdata,module, - "SamplesPerPixel tag is missing, " - "assuming correct SamplesPerPixel value is 3"); - if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3)) - goto bad; - } - if (tif->tif_dir.td_photometric==PHOTOMETRIC_YCBCR) - { - TIFFWarningExt(tif->tif_clientdata,module, - "SamplesPerPixel tag is missing, " - "applying correct SamplesPerPixel value of 3"); - if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3)) - goto bad; - } - else if ((tif->tif_dir.td_photometric==PHOTOMETRIC_MINISWHITE) - || (tif->tif_dir.td_photometric==PHOTOMETRIC_MINISBLACK)) - { - /* - * SamplesPerPixel tag is missing, but is not required - * by spec. Assume correct SamplesPerPixel value of 1. - */ - if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,1)) - goto bad; - } - } - } - /* - * Verify Palette image has a Colormap. - */ - if (tif->tif_dir.td_photometric == PHOTOMETRIC_PALETTE && - !TIFFFieldSet(tif, FIELD_COLORMAP)) { - if ( tif->tif_dir.td_bitspersample>=8 && tif->tif_dir.td_samplesperpixel==3) - tif->tif_dir.td_photometric = PHOTOMETRIC_RGB; - else if (tif->tif_dir.td_bitspersample>=8) - tif->tif_dir.td_photometric = PHOTOMETRIC_MINISBLACK; - else { - MissingRequired(tif, "Colormap"); - goto bad; - } - } - /* - * OJPEG hack: - * We do no further messing with strip/tile offsets/bytecounts in OJPEG - * TIFFs - */ - if (tif->tif_dir.td_compression!=COMPRESSION_OJPEG) - { - /* - * Attempt to deal with a missing StripByteCounts tag. - */ - if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) { - /* - * Some manufacturers violate the spec by not giving - * the size of the strips. In this case, assume there - * is one uncompressed strip of data. - */ - if ((tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG && - tif->tif_dir.td_nstrips > 1) || - (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE && - tif->tif_dir.td_nstrips != (uint32)tif->tif_dir.td_samplesperpixel)) { - MissingRequired(tif, "StripByteCounts"); - goto bad; - } - TIFFWarningExt(tif->tif_clientdata, module, - "TIFF directory is missing required " - "\"StripByteCounts\" field, calculating from imagelength"); - if (EstimateStripByteCounts(tif, dir, dircount) < 0) - goto bad; - /* - * Assume we have wrong StripByteCount value (in case - * of single strip) in following cases: - * - it is equal to zero along with StripOffset; - * - it is larger than file itself (in case of uncompressed - * image); - * - it is smaller than the size of the bytes per row - * multiplied on the number of rows. The last case should - * not be checked in the case of writing new image, - * because we may do not know the exact strip size - * until the whole image will be written and directory - * dumped out. - */ - #define BYTECOUNTLOOKSBAD \ - ( (tif->tif_dir.td_stripbytecount[0] == 0 && tif->tif_dir.td_stripoffset[0] != 0) || \ - (tif->tif_dir.td_compression == COMPRESSION_NONE && \ - tif->tif_dir.td_stripbytecount[0] > TIFFGetFileSize(tif) - tif->tif_dir.td_stripoffset[0]) || \ - (tif->tif_mode == O_RDONLY && \ - tif->tif_dir.td_compression == COMPRESSION_NONE && \ - tif->tif_dir.td_stripbytecount[0] < TIFFScanlineSize64(tif) * tif->tif_dir.td_imagelength) ) + default: + (void) TIFFFetchNormalTag(tif, dp, TRUE); + break; + } + } + /* + * OJPEG hack: + * - If a) compression is OJPEG, and b) photometric tag is missing, + * then we consistently find that photometric should be YCbCr + * - If a) compression is OJPEG, and b) photometric tag says it's RGB, + * then we consistently find that the buggy implementation of the + * buggy compression scheme matches photometric YCbCr instead. + * - If a) compression is OJPEG, and b) bitspersample tag is missing, + * then we consistently find bitspersample should be 8. + * - If a) compression is OJPEG, b) samplesperpixel tag is missing, + * and c) photometric is RGB or YCbCr, then we consistently find + * samplesperpixel should be 3 + * - If a) compression is OJPEG, b) samplesperpixel tag is missing, + * and c) photometric is MINISWHITE or MINISBLACK, then we consistently + * find samplesperpixel should be 3 + */ + if (tif->tif_dir.td_compression==COMPRESSION_OJPEG) + { + if (!TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) + { + TIFFWarningExt(tif->tif_clientdata, module, + "Photometric tag is missing, assuming data is YCbCr"); + if (!TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_YCBCR)) + goto bad; + } + else if (tif->tif_dir.td_photometric==PHOTOMETRIC_RGB) + { + tif->tif_dir.td_photometric=PHOTOMETRIC_YCBCR; + TIFFWarningExt(tif->tif_clientdata, module, + "Photometric tag value assumed incorrect, " + "assuming data is YCbCr instead of RGB"); + } + if (!TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) + { + TIFFWarningExt(tif->tif_clientdata,module, + "BitsPerSample tag is missing, assuming 8 bits per sample"); + if (!TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,8)) + goto bad; + } + if (!TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) + { + if (tif->tif_dir.td_photometric==PHOTOMETRIC_RGB) + { + TIFFWarningExt(tif->tif_clientdata,module, + "SamplesPerPixel tag is missing, " + "assuming correct SamplesPerPixel value is 3"); + if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3)) + goto bad; + } + if (tif->tif_dir.td_photometric==PHOTOMETRIC_YCBCR) + { + TIFFWarningExt(tif->tif_clientdata,module, + "SamplesPerPixel tag is missing, " + "applying correct SamplesPerPixel value of 3"); + if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3)) + goto bad; + } + else if ((tif->tif_dir.td_photometric==PHOTOMETRIC_MINISWHITE) + || (tif->tif_dir.td_photometric==PHOTOMETRIC_MINISBLACK)) + { + /* + * SamplesPerPixel tag is missing, but is not required + * by spec. Assume correct SamplesPerPixel value of 1. + */ + if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,1)) + goto bad; + } + } + } + /* + * Verify Palette image has a Colormap. + */ + if (tif->tif_dir.td_photometric == PHOTOMETRIC_PALETTE && + !TIFFFieldSet(tif, FIELD_COLORMAP)) { + if ( tif->tif_dir.td_bitspersample>=8 && tif->tif_dir.td_samplesperpixel==3) + tif->tif_dir.td_photometric = PHOTOMETRIC_RGB; + else if (tif->tif_dir.td_bitspersample>=8) + tif->tif_dir.td_photometric = PHOTOMETRIC_MINISBLACK; + else { + MissingRequired(tif, "Colormap"); + goto bad; + } + } + /* + * OJPEG hack: + * We do no further messing with strip/tile offsets/bytecounts in OJPEG + * TIFFs + */ + if (tif->tif_dir.td_compression!=COMPRESSION_OJPEG) + { + /* + * Attempt to deal with a missing StripByteCounts tag. + */ + if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) { + /* + * Some manufacturers violate the spec by not giving + * the size of the strips. In this case, assume there + * is one uncompressed strip of data. + */ + if ((tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG && + tif->tif_dir.td_nstrips > 1) || + (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE && + tif->tif_dir.td_nstrips != (uint32)tif->tif_dir.td_samplesperpixel)) { + MissingRequired(tif, "StripByteCounts"); + goto bad; + } + TIFFWarningExt(tif->tif_clientdata, module, + "TIFF directory is missing required " + "\"StripByteCounts\" field, calculating from imagelength"); + if (EstimateStripByteCounts(tif, dir, dircount) < 0) + goto bad; + /* + * Assume we have wrong StripByteCount value (in case + * of single strip) in following cases: + * - it is equal to zero along with StripOffset; + * - it is larger than file itself (in case of uncompressed + * image); + * - it is smaller than the size of the bytes per row + * multiplied on the number of rows. The last case should + * not be checked in the case of writing new image, + * because we may do not know the exact strip size + * until the whole image will be written and directory + * dumped out. + */ + #define BYTECOUNTLOOKSBAD \ + ( (tif->tif_dir.td_stripbytecount[0] == 0 && tif->tif_dir.td_stripoffset[0] != 0) || \ + (tif->tif_dir.td_compression == COMPRESSION_NONE && \ + (tif->tif_dir.td_stripoffset[0] <= TIFFGetFileSize(tif) && \ + tif->tif_dir.td_stripbytecount[0] > TIFFGetFileSize(tif) - tif->tif_dir.td_stripoffset[0])) || \ + (tif->tif_mode == O_RDONLY && \ + tif->tif_dir.td_compression == COMPRESSION_NONE && \ + tif->tif_dir.td_stripbytecount[0] < TIFFScanlineSize64(tif) * tif->tif_dir.td_imagelength) ) - } else if (tif->tif_dir.td_nstrips == 1 + } else if (tif->tif_dir.td_nstrips == 1 + && !(tif->tif_flags&TIFF_ISTILED) && _TIFFFillStriles(tif) - && tif->tif_dir.td_stripoffset[0] != 0 - && BYTECOUNTLOOKSBAD) { - /* - * XXX: Plexus (and others) sometimes give a value of - * zero for a tag when they don't know what the - * correct value is! Try and handle the simple case - * of estimating the size of a one strip image. - */ - TIFFWarningExt(tif->tif_clientdata, module, - "Bogus \"StripByteCounts\" field, ignoring and calculating from imagelength"); - if(EstimateStripByteCounts(tif, dir, dircount) < 0) - goto bad; + && tif->tif_dir.td_stripoffset[0] != 0 + && BYTECOUNTLOOKSBAD) { + /* + * XXX: Plexus (and others) sometimes give a value of + * zero for a tag when they don't know what the + * correct value is! Try and handle the simple case + * of estimating the size of a one strip image. + */ + TIFFWarningExt(tif->tif_clientdata, module, + "Bogus \"StripByteCounts\" field, ignoring and calculating from imagelength"); + if(EstimateStripByteCounts(tif, dir, dircount) < 0) + goto bad; #if !defined(DEFER_STRILE_LOAD) - } else if (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG - && tif->tif_dir.td_nstrips > 2 - && tif->tif_dir.td_compression == COMPRESSION_NONE - && tif->tif_dir.td_stripbytecount[0] != tif->tif_dir.td_stripbytecount[1] - && tif->tif_dir.td_stripbytecount[0] != 0 - && tif->tif_dir.td_stripbytecount[1] != 0 ) { - /* - * XXX: Some vendors fill StripByteCount array with - * absolutely wrong values (it can be equal to - * StripOffset array, for example). Catch this case - * here. + } else if (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG + && tif->tif_dir.td_nstrips > 2 + && tif->tif_dir.td_compression == COMPRESSION_NONE + && tif->tif_dir.td_stripbytecount[0] != tif->tif_dir.td_stripbytecount[1] + && tif->tif_dir.td_stripbytecount[0] != 0 + && tif->tif_dir.td_stripbytecount[1] != 0 ) { + /* + * XXX: Some vendors fill StripByteCount array with + * absolutely wrong values (it can be equal to + * StripOffset array, for example). Catch this case + * here. * * We avoid this check if deferring strile loading * as it would always force us to load the strip/tile * information. - */ - TIFFWarningExt(tif->tif_clientdata, module, - "Wrong \"StripByteCounts\" field, ignoring and calculating from imagelength"); - if (EstimateStripByteCounts(tif, dir, dircount) < 0) - goto bad; + */ + TIFFWarningExt(tif->tif_clientdata, module, + "Wrong \"StripByteCounts\" field, ignoring and calculating from imagelength"); + if (EstimateStripByteCounts(tif, dir, dircount) < 0) + goto bad; +#endif /* !defined(DEFER_STRILE_LOAD) */ + } + } + if (dir) + { + _TIFFfree(dir); + dir=NULL; + } + if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE)) + { + if (tif->tif_dir.td_bitspersample>=16) + tif->tif_dir.td_maxsamplevalue=0xFFFF; + else + tif->tif_dir.td_maxsamplevalue = (uint16)((1L<tif_dir.td_bitspersample)-1); + } + /* + * XXX: We can optimize checking for the strip bounds using the sorted + * bytecounts array. See also comments for TIFFAppendToStrip() + * function in tif_write.c. + */ +#if !defined(DEFER_STRILE_LOAD) + if (tif->tif_dir.td_nstrips > 1) { + uint32 strip; + + tif->tif_dir.td_stripbytecountsorted = 1; + for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) { + if (tif->tif_dir.td_stripoffset[strip - 1] > + tif->tif_dir.td_stripoffset[strip]) { + tif->tif_dir.td_stripbytecountsorted = 0; + break; + } + } + } #endif /* !defined(DEFER_STRILE_LOAD) */ - } - } - if (dir) - { - _TIFFfree(dir); - dir=NULL; - } - if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE)) - { - if (tif->tif_dir.td_bitspersample>=16) - tif->tif_dir.td_maxsamplevalue=0xFFFF; - else - tif->tif_dir.td_maxsamplevalue = (uint16)((1L<tif_dir.td_bitspersample)-1); - } - /* - * XXX: We can optimize checking for the strip bounds using the sorted - * bytecounts array. See also comments for TIFFAppendToStrip() - * function in tif_write.c. - */ -#if !defined(DEFER_STRILE_LOAD) - if (tif->tif_dir.td_nstrips > 1) { - uint32 strip; + + /* + * An opportunity for compression mode dependent tag fixup + */ + (*tif->tif_fixuptags)(tif); - tif->tif_dir.td_stripbytecountsorted = 1; - for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) { - if (tif->tif_dir.td_stripoffset[strip - 1] > - tif->tif_dir.td_stripoffset[strip]) { - tif->tif_dir.td_stripbytecountsorted = 0; - break; - } - } - } -#endif /* !defined(DEFER_STRILE_LOAD) */ - - /* - * An opportunity for compression mode dependent tag fixup - */ - (*tif->tif_fixuptags)(tif); - - /* - * Some manufacturers make life difficult by writing - * large amounts of uncompressed data as a single strip. - * This is contrary to the recommendations of the spec. - * The following makes an attempt at breaking such images - * into strips closer to the recommended 8k bytes. A - * side effect, however, is that the RowsPerStrip tag - * value may be changed. - */ - if ((tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG)&& - (tif->tif_dir.td_nstrips==1)&& - (tif->tif_dir.td_compression==COMPRESSION_NONE)&& - ((tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED))==TIFF_STRIPCHOP)) + /* + * Some manufacturers make life difficult by writing + * large amounts of uncompressed data as a single strip. + * This is contrary to the recommendations of the spec. + * The following makes an attempt at breaking such images + * into strips closer to the recommended 8k bytes. A + * side effect, however, is that the RowsPerStrip tag + * value may be changed. + */ + if ((tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG)&& + (tif->tif_dir.td_nstrips==1)&& + (tif->tif_dir.td_compression==COMPRESSION_NONE)&& + ((tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED))==TIFF_STRIPCHOP)) { if ( !_TIFFFillStriles(tif) || !tif->tif_dir.td_stripbytecount ) return 0; - ChopUpSingleUncompressedStrip(tif); + ChopUpSingleUncompressedStrip(tif); } /* - * Clear the dirty directory flag. + * Clear the dirty directory flag. */ - tif->tif_flags &= ~TIFF_DIRTYDIRECT; - tif->tif_flags &= ~TIFF_DIRTYSTRIP; + tif->tif_flags &= ~TIFF_DIRTYDIRECT; + tif->tif_flags &= ~TIFF_DIRTYSTRIP; - /* - * Reinitialize i/o since we are starting on a new directory. - */ - tif->tif_row = (uint32) -1; - tif->tif_curstrip = (uint32) -1; - tif->tif_col = (uint32) -1; - tif->tif_curtile = (uint32) -1; - tif->tif_tilesize = (tmsize_t) -1; + /* + * Reinitialize i/o since we are starting on a new directory. + */ + tif->tif_row = (uint32) -1; + tif->tif_curstrip = (uint32) -1; + tif->tif_col = (uint32) -1; + tif->tif_curtile = (uint32) -1; + tif->tif_tilesize = (tmsize_t) -1; - tif->tif_scanlinesize = TIFFScanlineSize(tif); - if (!tif->tif_scanlinesize) { - TIFFErrorExt(tif->tif_clientdata, module, - "Cannot handle zero scanline size"); - return (0); - } + tif->tif_scanlinesize = TIFFScanlineSize(tif); + if (!tif->tif_scanlinesize) { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot handle zero scanline size"); + return (0); + } - if (isTiled(tif)) { - tif->tif_tilesize = TIFFTileSize(tif); - if (!tif->tif_tilesize) { - TIFFErrorExt(tif->tif_clientdata, module, - "Cannot handle zero tile size"); - return (0); - } - } else { - if (!TIFFStripSize(tif)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Cannot handle zero strip size"); - return (0); - } - } - return (1); + if (isTiled(tif)) { + tif->tif_tilesize = TIFFTileSize(tif); + if (!tif->tif_tilesize) { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot handle zero tile size"); + return (0); + } + } else { + if (!TIFFStripSize(tif)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot handle zero strip size"); + return (0); + } + } + return (1); bad: - if (dir) - _TIFFfree(dir); - return (0); + if (dir) + _TIFFfree(dir); + return (0); } static void TIFFReadDirectoryCheckOrder(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) { - static const char module[] = "TIFFReadDirectoryCheckOrder"; - uint16 m; - uint16 n; - TIFFDirEntry* o; - m=0; - for (n=0, o=dir; ntdir_tagtif_clientdata,module, - "Invalid TIFF directory; tags are not sorted in ascending order"); - break; - } - m=o->tdir_tag+1; - } + static const char module[] = "TIFFReadDirectoryCheckOrder"; + uint16 m; + uint16 n; + TIFFDirEntry* o; + m=0; + for (n=0, o=dir; ntdir_tagtif_clientdata,module, + "Invalid TIFF directory; tags are not sorted in ascending order"); + break; + } + m=o->tdir_tag+1; + } } static TIFFDirEntry* TIFFReadDirectoryFindEntry(TIFF* tif, TIFFDirEntry* dir, uint16 dircount, uint16 tagid) { - TIFFDirEntry* m; - uint16 n; - (void) tif; - for (m=dir, n=0; ntdir_tag==tagid) - return(m); - } - return(0); + TIFFDirEntry* m; + uint16 n; + (void) tif; + for (m=dir, n=0; ntdir_tag==tagid) + return(m); + } + return(0); } static void TIFFReadDirectoryFindFieldInfo(TIFF* tif, uint16 tagid, uint32* fii) { - int32 ma,mb,mc; - ma=-1; - mc=(int32)tif->tif_nfields; - while (1) - { - if (ma+1==mc) - { - *fii = FAILED_FII; - return; - } - mb=(ma+mc)/2; - if (tif->tif_fields[mb]->field_tag==(uint32)tagid) - break; - if (tif->tif_fields[mb]->field_tag<(uint32)tagid) - ma=mb; - else - mc=mb; - } - while (1) - { - if (mb==0) - break; - if (tif->tif_fields[mb-1]->field_tag!=(uint32)tagid) - break; - mb--; - } - *fii=mb; + int32 ma,mb,mc; + ma=-1; + mc=(int32)tif->tif_nfields; + while (1) + { + if (ma+1==mc) + { + *fii = FAILED_FII; + return; + } + mb=(ma+mc)/2; + if (tif->tif_fields[mb]->field_tag==(uint32)tagid) + break; + if (tif->tif_fields[mb]->field_tag<(uint32)tagid) + ma=mb; + else + mc=mb; + } + while (1) + { + if (mb==0) + break; + if (tif->tif_fields[mb-1]->field_tag!=(uint32)tagid) + break; + mb--; + } + *fii=mb; } /* - * Read custom directory from the arbitarry offset. + * Read custom directory from the arbitrary offset. * The code is very similar to TIFFReadDirectory(). */ int TIFFReadCustomDirectory(TIFF* tif, toff_t diroff, - const TIFFFieldArray* infoarray) + const TIFFFieldArray* infoarray) { - static const char module[] = "TIFFReadCustomDirectory"; - TIFFDirEntry* dir; - uint16 dircount; - TIFFDirEntry* dp; - uint16 di; - const TIFFField* fip; - uint32 fii; - _TIFFSetupFields(tif, infoarray); - dircount=TIFFFetchDirectory(tif,diroff,&dir,NULL); - if (!dircount) - { - TIFFErrorExt(tif->tif_clientdata,module, - "Failed to read custom directory at offset " TIFF_UINT64_FORMAT,diroff); - return 0; - } - TIFFFreeDirectory(tif); - _TIFFmemset(&tif->tif_dir, 0, sizeof(TIFFDirectory)); - TIFFReadDirectoryCheckOrder(tif,dir,dircount); - for (di=0, dp=dir; ditdir_tag,&fii); - if (fii == FAILED_FII) - { - TIFFWarningExt(tif->tif_clientdata, module, - "Unknown field with tag %d (0x%x) encountered", - dp->tdir_tag, dp->tdir_tag); - if (!_TIFFMergeFields(tif, _TIFFCreateAnonField(tif, - dp->tdir_tag, - (TIFFDataType) dp->tdir_type), - 1)) { - TIFFWarningExt(tif->tif_clientdata, module, - "Registering anonymous field with tag %d (0x%x) failed", - dp->tdir_tag, dp->tdir_tag); - dp->tdir_tag=IGNORE; - } else { - TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); - assert( fii != FAILED_FII ); - } - } - if (dp->tdir_tag!=IGNORE) - { - fip=tif->tif_fields[fii]; - if (fip->field_bit==FIELD_IGNORE) - dp->tdir_tag=IGNORE; - else - { - /* check data type */ - while ((fip->field_type!=TIFF_ANY)&&(fip->field_type!=dp->tdir_type)) - { - fii++; - if ((fii==tif->tif_nfields)|| - (tif->tif_fields[fii]->field_tag!=(uint32)dp->tdir_tag)) - { - fii=0xFFFF; - break; - } - fip=tif->tif_fields[fii]; - } - if (fii==0xFFFF) - { - TIFFWarningExt(tif->tif_clientdata, module, - "Wrong data type %d for \"%s\"; tag ignored", - dp->tdir_type,fip->field_name); - dp->tdir_tag=IGNORE; - } - else - { - /* check count if known in advance */ - if ((fip->field_readcount!=TIFF_VARIABLE)&& - (fip->field_readcount!=TIFF_VARIABLE2)) - { - uint32 expected; - if (fip->field_readcount==TIFF_SPP) - expected=(uint32)tif->tif_dir.td_samplesperpixel; - else - expected=(uint32)fip->field_readcount; - if (!CheckDirCount(tif,dp,expected)) - dp->tdir_tag=IGNORE; - } - } - } - switch (dp->tdir_tag) - { - case IGNORE: - break; - case EXIFTAG_SUBJECTDISTANCE: - (void) TIFFFetchSubjectDistance(tif,dp); - break; - default: - (void) TIFFFetchNormalTag(tif, dp, TRUE); - break; - } - } - } - if (dir) - _TIFFfree(dir); - return 1; + static const char module[] = "TIFFReadCustomDirectory"; + TIFFDirEntry* dir; + uint16 dircount; + TIFFDirEntry* dp; + uint16 di; + const TIFFField* fip; + uint32 fii; + _TIFFSetupFields(tif, infoarray); + dircount=TIFFFetchDirectory(tif,diroff,&dir,NULL); + if (!dircount) + { + TIFFErrorExt(tif->tif_clientdata,module, + "Failed to read custom directory at offset " TIFF_UINT64_FORMAT,diroff); + return 0; + } + TIFFFreeDirectory(tif); + _TIFFmemset(&tif->tif_dir, 0, sizeof(TIFFDirectory)); + TIFFReadDirectoryCheckOrder(tif,dir,dircount); + for (di=0, dp=dir; ditdir_tag,&fii); + if (fii == FAILED_FII) + { + TIFFWarningExt(tif->tif_clientdata, module, + "Unknown field with tag %d (0x%x) encountered", + dp->tdir_tag, dp->tdir_tag); + if (!_TIFFMergeFields(tif, _TIFFCreateAnonField(tif, + dp->tdir_tag, + (TIFFDataType) dp->tdir_type), + 1)) { + TIFFWarningExt(tif->tif_clientdata, module, + "Registering anonymous field with tag %d (0x%x) failed", + dp->tdir_tag, dp->tdir_tag); + dp->tdir_tag=IGNORE; + } else { + TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); + assert( fii != FAILED_FII ); + } + } + if (dp->tdir_tag!=IGNORE) + { + fip=tif->tif_fields[fii]; + if (fip->field_bit==FIELD_IGNORE) + dp->tdir_tag=IGNORE; + else + { + /* check data type */ + while ((fip->field_type!=TIFF_ANY)&&(fip->field_type!=dp->tdir_type)) + { + fii++; + if ((fii==tif->tif_nfields)|| + (tif->tif_fields[fii]->field_tag!=(uint32)dp->tdir_tag)) + { + fii=0xFFFF; + break; + } + fip=tif->tif_fields[fii]; + } + if (fii==0xFFFF) + { + TIFFWarningExt(tif->tif_clientdata, module, + "Wrong data type %d for \"%s\"; tag ignored", + dp->tdir_type,fip->field_name); + dp->tdir_tag=IGNORE; + } + else + { + /* check count if known in advance */ + if ((fip->field_readcount!=TIFF_VARIABLE)&& + (fip->field_readcount!=TIFF_VARIABLE2)) + { + uint32 expected; + if (fip->field_readcount==TIFF_SPP) + expected=(uint32)tif->tif_dir.td_samplesperpixel; + else + expected=(uint32)fip->field_readcount; + if (!CheckDirCount(tif,dp,expected)) + dp->tdir_tag=IGNORE; + } + } + } + switch (dp->tdir_tag) + { + case IGNORE: + break; + case EXIFTAG_SUBJECTDISTANCE: + (void) TIFFFetchSubjectDistance(tif,dp); + break; + default: + (void) TIFFFetchNormalTag(tif, dp, TRUE); + break; + } + } + } + if (dir) + _TIFFfree(dir); + return 1; } /* @@ -4259,104 +4409,110 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff, int TIFFReadEXIFDirectory(TIFF* tif, toff_t diroff) { - const TIFFFieldArray* exifFieldArray; - exifFieldArray = _TIFFGetExifFields(); - return TIFFReadCustomDirectory(tif, diroff, exifFieldArray); + const TIFFFieldArray* exifFieldArray; + exifFieldArray = _TIFFGetExifFields(); + return TIFFReadCustomDirectory(tif, diroff, exifFieldArray); } static int EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) { - static const char module[] = "EstimateStripByteCounts"; + static const char module[] = "EstimateStripByteCounts"; - TIFFDirEntry *dp; - TIFFDirectory *td = &tif->tif_dir; - uint32 strip; + TIFFDirEntry *dp; + TIFFDirectory *td = &tif->tif_dir; + uint32 strip; - _TIFFFillStriles( tif ); + /* Do not try to load stripbytecount as we will compute it */ + if( !_TIFFFillStrilesInternal( tif, 0 ) ) + return -1; - if (td->td_stripbytecount) - _TIFFfree(td->td_stripbytecount); - td->td_stripbytecount = (uint64*) - _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), - "for \"StripByteCounts\" array"); + if (td->td_stripbytecount) + _TIFFfree(td->td_stripbytecount); + td->td_stripbytecount = (uint64*) + _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), + "for \"StripByteCounts\" array"); if( td->td_stripbytecount == NULL ) return -1; - if (td->td_compression != COMPRESSION_NONE) { - uint64 space; - uint64 filesize; - uint16 n; - filesize = TIFFGetFileSize(tif); - if (!(tif->tif_flags&TIFF_BIGTIFF)) - space=sizeof(TIFFHeaderClassic)+2+dircount*12+4; - else - space=sizeof(TIFFHeaderBig)+8+dircount*20+8; - /* calculate amount of space used by indirect values */ - for (dp = dir, n = dircount; n > 0; n--, dp++) - { - uint32 typewidth = TIFFDataWidth((TIFFDataType) dp->tdir_type); - uint64 datasize; - typewidth = TIFFDataWidth((TIFFDataType) dp->tdir_type); - if (typewidth == 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "Cannot determine size of unknown tag type %d", - dp->tdir_type); - return -1; - } - datasize=(uint64)typewidth*dp->tdir_count; - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - if (datasize<=4) - datasize=0; - } - else - { - if (datasize<=8) - datasize=0; - } - space+=datasize; - } - space = filesize - space; - if (td->td_planarconfig == PLANARCONFIG_SEPARATE) - space /= td->td_samplesperpixel; - for (strip = 0; strip < td->td_nstrips; strip++) - td->td_stripbytecount[strip] = space; - /* - * This gross hack handles the case were the offset to - * the last strip is past the place where we think the strip - * should begin. Since a strip of data must be contiguous, - * it's safe to assume that we've overestimated the amount - * of data in the strip and trim this number back accordingly. - */ - strip--; - if (td->td_stripoffset[strip]+td->td_stripbytecount[strip] > filesize) - td->td_stripbytecount[strip] = filesize - td->td_stripoffset[strip]; - } else if (isTiled(tif)) { - uint64 bytespertile = TIFFTileSize64(tif); + if (td->td_compression != COMPRESSION_NONE) { + uint64 space; + uint64 filesize; + uint16 n; + filesize = TIFFGetFileSize(tif); + if (!(tif->tif_flags&TIFF_BIGTIFF)) + space=sizeof(TIFFHeaderClassic)+2+dircount*12+4; + else + space=sizeof(TIFFHeaderBig)+8+dircount*20+8; + /* calculate amount of space used by indirect values */ + for (dp = dir, n = dircount; n > 0; n--, dp++) + { + uint32 typewidth; + uint64 datasize; + typewidth = TIFFDataWidth((TIFFDataType) dp->tdir_type); + if (typewidth == 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot determine size of unknown tag type %d", + dp->tdir_type); + return -1; + } + datasize=(uint64)typewidth*dp->tdir_count; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + if (datasize<=4) + datasize=0; + } + else + { + if (datasize<=8) + datasize=0; + } + space+=datasize; + } + if( filesize < space ) + /* we should perhaps return in error ? */ + space = filesize; + else + space = filesize - space; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + space /= td->td_samplesperpixel; + for (strip = 0; strip < td->td_nstrips; strip++) + td->td_stripbytecount[strip] = space; + /* + * This gross hack handles the case were the offset to + * the last strip is past the place where we think the strip + * should begin. Since a strip of data must be contiguous, + * it's safe to assume that we've overestimated the amount + * of data in the strip and trim this number back accordingly. + */ + strip--; + if (td->td_stripoffset[strip]+td->td_stripbytecount[strip] > filesize) + td->td_stripbytecount[strip] = filesize - td->td_stripoffset[strip]; + } else if (isTiled(tif)) { + uint64 bytespertile = TIFFTileSize64(tif); - for (strip = 0; strip < td->td_nstrips; strip++) - td->td_stripbytecount[strip] = bytespertile; - } else { - uint64 rowbytes = TIFFScanlineSize64(tif); - uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage; - for (strip = 0; strip < td->td_nstrips; strip++) - td->td_stripbytecount[strip] = rowbytes * rowsperstrip; - } - TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); - if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP)) - td->td_rowsperstrip = td->td_imagelength; - return 1; + for (strip = 0; strip < td->td_nstrips; strip++) + td->td_stripbytecount[strip] = bytespertile; + } else { + uint64 rowbytes = TIFFScanlineSize64(tif); + uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage; + for (strip = 0; strip < td->td_nstrips; strip++) + td->td_stripbytecount[strip] = rowbytes * rowsperstrip; + } + TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); + if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP)) + td->td_rowsperstrip = td->td_imagelength; + return 1; } static void MissingRequired(TIFF* tif, const char* tagname) { - static const char module[] = "MissingRequired"; + static const char module[] = "MissingRequired"; - TIFFErrorExt(tif->tif_clientdata, module, - "TIFF directory is missing required \"%s\" field", - tagname); + TIFFErrorExt(tif->tif_clientdata, module, + "TIFF directory is missing required \"%s\" field", + tagname); } /* @@ -4368,36 +4524,44 @@ MissingRequired(TIFF* tif, const char* tagname) static int TIFFCheckDirOffset(TIFF* tif, uint64 diroff) { - uint16 n; + uint16 n; - if (diroff == 0) /* no more directories */ - return 0; + if (diroff == 0) /* no more directories */ + return 0; + if (tif->tif_dirnumber == 65535) { + TIFFErrorExt(tif->tif_clientdata, "TIFFCheckDirOffset", + "Cannot handle more than 65535 TIFF directories"); + return 0; + } - for (n = 0; n < tif->tif_dirnumber && tif->tif_dirlist; n++) { - if (tif->tif_dirlist[n] == diroff) - return 0; - } + for (n = 0; n < tif->tif_dirnumber && tif->tif_dirlist; n++) { + if (tif->tif_dirlist[n] == diroff) + return 0; + } - tif->tif_dirnumber++; + tif->tif_dirnumber++; - if (tif->tif_dirnumber > tif->tif_dirlistsize) { - uint64* new_dirlist; + if (tif->tif_dirlist == NULL || tif->tif_dirnumber > tif->tif_dirlistsize) { + uint64* new_dirlist; - /* - * XXX: Reduce memory allocation granularity of the dirlist - * array. - */ - new_dirlist = (uint64*)_TIFFCheckRealloc(tif, tif->tif_dirlist, - tif->tif_dirnumber, 2 * sizeof(uint64), "for IFD list"); - if (!new_dirlist) - return 0; - tif->tif_dirlistsize = 2 * tif->tif_dirnumber; - tif->tif_dirlist = new_dirlist; - } + /* + * XXX: Reduce memory allocation granularity of the dirlist + * array. + */ + new_dirlist = (uint64*)_TIFFCheckRealloc(tif, tif->tif_dirlist, + tif->tif_dirnumber, 2 * sizeof(uint64), "for IFD list"); + if (!new_dirlist) + return 0; + if( tif->tif_dirnumber >= 32768 ) + tif->tif_dirlistsize = 65535; + else + tif->tif_dirlistsize = 2 * tif->tif_dirnumber; + tif->tif_dirlist = new_dirlist; + } - tif->tif_dirlist[tif->tif_dirnumber - 1] = diroff; + tif->tif_dirlist[tif->tif_dirnumber - 1] = diroff; - return 1; + return 1; } /* @@ -4407,23 +4571,23 @@ TIFFCheckDirOffset(TIFF* tif, uint64 diroff) static int CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count) { - if ((uint64)count > dir->tdir_count) { - const TIFFField* fip = TIFFFieldWithTag(tif, dir->tdir_tag); - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, - "incorrect count for field \"%s\" (" TIFF_UINT64_FORMAT ", expecting %u); tag ignored", - fip ? fip->field_name : "unknown tagname", - dir->tdir_count, count); - return (0); - } else if ((uint64)count < dir->tdir_count) { - const TIFFField* fip = TIFFFieldWithTag(tif, dir->tdir_tag); - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, - "incorrect count for field \"%s\" (" TIFF_UINT64_FORMAT ", expecting %u); tag trimmed", - fip ? fip->field_name : "unknown tagname", - dir->tdir_count, count); - dir->tdir_count = count; - return (1); - } - return (1); + if ((uint64)count > dir->tdir_count) { + const TIFFField* fip = TIFFFieldWithTag(tif, dir->tdir_tag); + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "incorrect count for field \"%s\" (" TIFF_UINT64_FORMAT ", expecting %u); tag ignored", + fip ? fip->field_name : "unknown tagname", + dir->tdir_count, count); + return (0); + } else if ((uint64)count < dir->tdir_count) { + const TIFFField* fip = TIFFFieldWithTag(tif, dir->tdir_tag); + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "incorrect count for field \"%s\" (" TIFF_UINT64_FORMAT ", expecting %u); tag trimmed", + fip ? fip->field_name : "unknown tagname", + dir->tdir_count, count); + dir->tdir_count = count; + return (1); + } + return (1); } /* @@ -4435,253 +4599,252 @@ static uint16 TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, uint64 *nextdiroff) { - static const char module[] = "TIFFFetchDirectory"; + static const char module[] = "TIFFFetchDirectory"; - void* origdir; - uint16 dircount16; - uint32 dirsize; - TIFFDirEntry* dir; - uint8* ma; - TIFFDirEntry* mb; - uint16 n; + void* origdir; + uint16 dircount16; + uint32 dirsize; + TIFFDirEntry* dir; + uint8* ma; + TIFFDirEntry* mb; + uint16 n; - assert(pdir); + assert(pdir); - tif->tif_diroff = diroff; - if (nextdiroff) - *nextdiroff = 0; - if (!isMapped(tif)) { - if (!SeekOK(tif, tif->tif_diroff)) { - TIFFErrorExt(tif->tif_clientdata, module, - "%s: Seek error accessing TIFF directory", - tif->tif_name); - return 0; - } - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - if (!ReadOK(tif, &dircount16, sizeof (uint16))) { - TIFFErrorExt(tif->tif_clientdata, module, - "%s: Can not read TIFF directory count", - tif->tif_name); - return 0; - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabShort(&dircount16); - if (dircount16>4096) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Sanity check on directory count failed, this is probably not a valid IFD offset"); - return 0; - } - dirsize = 12; - } else { - uint64 dircount64; - if (!ReadOK(tif, &dircount64, sizeof (uint64))) { - TIFFErrorExt(tif->tif_clientdata, module, - "%s: Can not read TIFF directory count", - tif->tif_name); - return 0; - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(&dircount64); - if (dircount64>4096) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Sanity check on directory count failed, this is probably not a valid IFD offset"); - return 0; - } - dircount16 = (uint16)dircount64; - dirsize = 20; - } - origdir = _TIFFCheckMalloc(tif, dircount16, - dirsize, "to read TIFF directory"); - if (origdir == NULL) - return 0; - if (!ReadOK(tif, origdir, (tmsize_t)(dircount16*dirsize))) { - TIFFErrorExt(tif->tif_clientdata, module, - "%.100s: Can not read TIFF directory", - tif->tif_name); - _TIFFfree(origdir); - return 0; - } - /* - * Read offset to next directory for sequential scans if - * needed. - */ - if (nextdiroff) - { - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - uint32 nextdiroff32; - if (!ReadOK(tif, &nextdiroff32, sizeof(uint32))) - nextdiroff32 = 0; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&nextdiroff32); - *nextdiroff=nextdiroff32; - } else { - if (!ReadOK(tif, nextdiroff, sizeof(uint64))) - *nextdiroff = 0; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8(nextdiroff); - } - } - } else { - tmsize_t m; - tmsize_t off = (tmsize_t) tif->tif_diroff; - if ((uint64)off!=tif->tif_diroff) - { - TIFFErrorExt(tif->tif_clientdata,module,"Can not read TIFF directory count"); - return(0); - } + tif->tif_diroff = diroff; + if (nextdiroff) + *nextdiroff = 0; + if (!isMapped(tif)) { + if (!SeekOK(tif, tif->tif_diroff)) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Seek error accessing TIFF directory", + tif->tif_name); + return 0; + } + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + if (!ReadOK(tif, &dircount16, sizeof (uint16))) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Can not read TIFF directory count", + tif->tif_name); + return 0; + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount16); + if (dircount16>4096) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Sanity check on directory count failed, this is probably not a valid IFD offset"); + return 0; + } + dirsize = 12; + } else { + uint64 dircount64; + if (!ReadOK(tif, &dircount64, sizeof (uint64))) { + TIFFErrorExt(tif->tif_clientdata, module, + "%s: Can not read TIFF directory count", + tif->tif_name); + return 0; + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8(&dircount64); + if (dircount64>4096) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Sanity check on directory count failed, this is probably not a valid IFD offset"); + return 0; + } + dircount16 = (uint16)dircount64; + dirsize = 20; + } + origdir = _TIFFCheckMalloc(tif, dircount16, + dirsize, "to read TIFF directory"); + if (origdir == NULL) + return 0; + if (!ReadOK(tif, origdir, (tmsize_t)(dircount16*dirsize))) { + TIFFErrorExt(tif->tif_clientdata, module, + "%.100s: Can not read TIFF directory", + tif->tif_name); + _TIFFfree(origdir); + return 0; + } + /* + * Read offset to next directory for sequential scans if + * needed. + */ + if (nextdiroff) + { + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + uint32 nextdiroff32; + if (!ReadOK(tif, &nextdiroff32, sizeof(uint32))) + nextdiroff32 = 0; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&nextdiroff32); + *nextdiroff=nextdiroff32; + } else { + if (!ReadOK(tif, nextdiroff, sizeof(uint64))) + *nextdiroff = 0; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8(nextdiroff); + } + } + } else { + tmsize_t m; + tmsize_t off = (tmsize_t) tif->tif_diroff; + if ((uint64)off!=tif->tif_diroff) + { + TIFFErrorExt(tif->tif_clientdata,module,"Can not read TIFF directory count"); + return(0); + } - /* - * Check for integer overflow when validating the dir_off, - * otherwise a very high offset may cause an OOB read and - * crash the client. Make two comparisons instead of - * - * off + sizeof(uint16) > tif->tif_size - * - * to avoid overflow. - */ - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - m=off+sizeof(uint16); - if ((mtif->tif_size)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Can not read TIFF directory count"); - return 0; - } else { - _TIFFmemcpy(&dircount16, tif->tif_base + off, - sizeof(uint16)); - } - off += sizeof (uint16); - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabShort(&dircount16); - if (dircount16>4096) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Sanity check on directory count failed, this is probably not a valid IFD offset"); - return 0; - } - dirsize = 12; - } - else - { - tmsize_t m; - uint64 dircount64; - m=off+sizeof(uint64); - if ((mtif->tif_size)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Can not read TIFF directory count"); - return 0; - } else { - _TIFFmemcpy(&dircount64, tif->tif_base + off, - sizeof(uint64)); - } - off += sizeof (uint64); - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(&dircount64); - if (dircount64>4096) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Sanity check on directory count failed, this is probably not a valid IFD offset"); - return 0; - } - dircount16 = (uint16)dircount64; - dirsize = 20; - } - if (dircount16 == 0 ) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Sanity check on directory count failed, zero tag directories not supported"); - return 0; - } - origdir = _TIFFCheckMalloc(tif, dircount16, - dirsize, - "to read TIFF directory"); - if (origdir == NULL) - return 0; - m=off+dircount16*dirsize; - if ((mtif->tif_size)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Can not read TIFF directory"); - _TIFFfree(origdir); - return 0; - } else { - _TIFFmemcpy(origdir, tif->tif_base + off, - dircount16 * dirsize); - } - if (nextdiroff) { - off += dircount16 * dirsize; - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - uint32 nextdiroff32; - m=off+sizeof(uint32); - if ((mtif->tif_size)) - nextdiroff32 = 0; - else - _TIFFmemcpy(&nextdiroff32, tif->tif_base + off, - sizeof (uint32)); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&nextdiroff32); - *nextdiroff = nextdiroff32; - } - else - { - m=off+sizeof(uint64); - if ((mtif->tif_size)) - *nextdiroff = 0; - else - _TIFFmemcpy(nextdiroff, tif->tif_base + off, - sizeof (uint64)); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8(nextdiroff); - } - } - } - dir = (TIFFDirEntry*)_TIFFCheckMalloc(tif, dircount16, - sizeof(TIFFDirEntry), - "to read TIFF directory"); - if (dir==0) - { - _TIFFfree(origdir); - return 0; - } - ma=(uint8*)origdir; - mb=dir; - for (n=0; ntif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)ma); - mb->tdir_tag=*(uint16*)ma; - ma+=sizeof(uint16); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)ma); - mb->tdir_type=*(uint16*)ma; - ma+=sizeof(uint16); - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)ma); - mb->tdir_count=(uint64)(*(uint32*)ma); - ma+=sizeof(uint32); - *(uint32*)(&mb->tdir_offset)=*(uint32*)ma; - ma+=sizeof(uint32); - } - else - { - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)ma); + /* + * Check for integer overflow when validating the dir_off, + * otherwise a very high offset may cause an OOB read and + * crash the client. Make two comparisons instead of + * + * off + sizeof(uint16) > tif->tif_size + * + * to avoid overflow. + */ + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + m=off+sizeof(uint16); + if ((mtif->tif_size)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Can not read TIFF directory count"); + return 0; + } else { + _TIFFmemcpy(&dircount16, tif->tif_base + off, + sizeof(uint16)); + } + off += sizeof (uint16); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount16); + if (dircount16>4096) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Sanity check on directory count failed, this is probably not a valid IFD offset"); + return 0; + } + dirsize = 12; + } + else + { + uint64 dircount64; + m=off+sizeof(uint64); + if ((mtif->tif_size)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Can not read TIFF directory count"); + return 0; + } else { + _TIFFmemcpy(&dircount64, tif->tif_base + off, + sizeof(uint64)); + } + off += sizeof (uint64); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8(&dircount64); + if (dircount64>4096) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Sanity check on directory count failed, this is probably not a valid IFD offset"); + return 0; + } + dircount16 = (uint16)dircount64; + dirsize = 20; + } + if (dircount16 == 0 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Sanity check on directory count failed, zero tag directories not supported"); + return 0; + } + origdir = _TIFFCheckMalloc(tif, dircount16, + dirsize, + "to read TIFF directory"); + if (origdir == NULL) + return 0; + m=off+dircount16*dirsize; + if ((mtif->tif_size)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Can not read TIFF directory"); + _TIFFfree(origdir); + return 0; + } else { + _TIFFmemcpy(origdir, tif->tif_base + off, + dircount16 * dirsize); + } + if (nextdiroff) { + off += dircount16 * dirsize; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + uint32 nextdiroff32; + m=off+sizeof(uint32); + if ((mtif->tif_size)) + nextdiroff32 = 0; + else + _TIFFmemcpy(&nextdiroff32, tif->tif_base + off, + sizeof (uint32)); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&nextdiroff32); + *nextdiroff = nextdiroff32; + } + else + { + m=off+sizeof(uint64); + if ((mtif->tif_size)) + *nextdiroff = 0; + else + _TIFFmemcpy(nextdiroff, tif->tif_base + off, + sizeof (uint64)); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8(nextdiroff); + } + } + } + dir = (TIFFDirEntry*)_TIFFCheckMalloc(tif, dircount16, + sizeof(TIFFDirEntry), + "to read TIFF directory"); + if (dir==0) + { + _TIFFfree(origdir); + return 0; + } + ma=(uint8*)origdir; + mb=dir; + for (n=0; ntif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)ma); + mb->tdir_tag=*(uint16*)ma; + ma+=sizeof(uint16); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)ma); + mb->tdir_type=*(uint16*)ma; + ma+=sizeof(uint16); + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)ma); + mb->tdir_count=(uint64)(*(uint32*)ma); + ma+=sizeof(uint32); + *(uint32*)(&mb->tdir_offset)=*(uint32*)ma; + ma+=sizeof(uint32); + } + else + { + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)ma); mb->tdir_count=TIFFReadUInt64(ma); - ma+=sizeof(uint64); - mb->tdir_offset.toff_long8=TIFFReadUInt64(ma); - ma+=sizeof(uint64); - } - mb++; - } - _TIFFfree(origdir); - *pdir = dir; - return dircount16; + ma+=sizeof(uint64); + mb->tdir_offset.toff_long8=TIFFReadUInt64(ma); + ma+=sizeof(uint64); + } + mb++; + } + _TIFFfree(origdir); + *pdir = dir; + return dircount16; } /* @@ -4690,11 +4853,11 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, static int TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover) { - static const char module[] = "TIFFFetchNormalTag"; - enum TIFFReadDirEntryErr err; - uint32 fii; - const TIFFField* fip = NULL; - TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); + static const char module[] = "TIFFFetchNormalTag"; + enum TIFFReadDirEntryErr err; + uint32 fii; + const TIFFField* fip = NULL; + TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); if( fii == FAILED_FII ) { TIFFErrorExt(tif->tif_clientdata, "TIFFFetchNormalTag", @@ -4702,650 +4865,669 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover) dp->tdir_tag); return 0; } - fip=tif->tif_fields[fii]; - assert(fip->set_field_type!=TIFF_SETGET_OTHER); /* if so, we shouldn't arrive here but deal with this in specialized code */ - assert(fip->set_field_type!=TIFF_SETGET_INT); /* if so, we shouldn't arrive here as this is only the case for pseudo-tags */ - err=TIFFReadDirEntryErrOk; - switch (fip->set_field_type) - { - case TIFF_SETGET_UNDEFINED: - break; - case TIFF_SETGET_ASCII: - { - uint8* data; - assert(fip->field_passcount==0); - err=TIFFReadDirEntryByteArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - uint8* ma; - uint32 mb; - int n; - ma=data; - mb=0; - while (mb<(uint32)dp->tdir_count) - { - if (*ma==0) - break; - ma++; - mb++; - } - if (mb+1<(uint32)dp->tdir_count) - TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" contains null byte in value; value incorrectly truncated during reading due to implementation limitations",fip->field_name); - else if (mb+1>(uint32)dp->tdir_count) - { - uint8* o; - TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte",fip->field_name); - if ((uint32)dp->tdir_count+1!=dp->tdir_count+1) - o=NULL; - else - o=_TIFFmalloc((uint32)dp->tdir_count+1); - if (o==NULL) + fip=tif->tif_fields[fii]; + assert(fip != NULL); /* should not happen */ + assert(fip->set_field_type!=TIFF_SETGET_OTHER); /* if so, we shouldn't arrive here but deal with this in specialized code */ + assert(fip->set_field_type!=TIFF_SETGET_INT); /* if so, we shouldn't arrive here as this is only the case for pseudo-tags */ + err=TIFFReadDirEntryErrOk; + switch (fip->set_field_type) + { + case TIFF_SETGET_UNDEFINED: + break; + case TIFF_SETGET_ASCII: + { + uint8* data; + assert(fip->field_passcount==0); + err=TIFFReadDirEntryByteArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + uint8* ma; + uint32 mb; + int n; + ma=data; + mb=0; + while (mb<(uint32)dp->tdir_count) + { + if (*ma==0) + break; + ma++; + mb++; + } + if (mb+1<(uint32)dp->tdir_count) + TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" contains null byte in value; value incorrectly truncated during reading due to implementation limitations",fip->field_name); + else if (mb+1>(uint32)dp->tdir_count) + { + uint8* o; + TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte",fip->field_name); + if ((uint32)dp->tdir_count+1!=dp->tdir_count+1) + o=NULL; + else + o=_TIFFmalloc((uint32)dp->tdir_count+1); + if (o==NULL) + { + if (data!=NULL) + _TIFFfree(data); + return(0); + } + _TIFFmemcpy(o,data,(uint32)dp->tdir_count); + o[(uint32)dp->tdir_count]=0; + if (data!=0) + _TIFFfree(data); + data=o; + } + n=TIFFSetField(tif,dp->tdir_tag,data); + if (data!=0) + _TIFFfree(data); + if (!n) + return(0); + } + } + break; + case TIFF_SETGET_UINT8: + { + uint8 data=0; + assert(fip->field_readcount==1); + assert(fip->field_passcount==0); + err=TIFFReadDirEntryByte(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + if (!TIFFSetField(tif,dp->tdir_tag,data)) + return(0); + } + } + break; + case TIFF_SETGET_UINT16: + { + uint16 data; + assert(fip->field_readcount==1); + assert(fip->field_passcount==0); + err=TIFFReadDirEntryShort(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + if (!TIFFSetField(tif,dp->tdir_tag,data)) + return(0); + } + } + break; + case TIFF_SETGET_UINT32: + { + uint32 data; + assert(fip->field_readcount==1); + assert(fip->field_passcount==0); + err=TIFFReadDirEntryLong(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + if (!TIFFSetField(tif,dp->tdir_tag,data)) + return(0); + } + } + break; + case TIFF_SETGET_UINT64: + { + uint64 data; + assert(fip->field_readcount==1); + assert(fip->field_passcount==0); + err=TIFFReadDirEntryLong8(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + if (!TIFFSetField(tif,dp->tdir_tag,data)) + return(0); + } + } + break; + case TIFF_SETGET_FLOAT: + { + float data; + assert(fip->field_readcount==1); + assert(fip->field_passcount==0); + err=TIFFReadDirEntryFloat(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + if (!TIFFSetField(tif,dp->tdir_tag,data)) + return(0); + } + } + break; + case TIFF_SETGET_DOUBLE: + { + double data; + assert(fip->field_readcount==1); + assert(fip->field_passcount==0); + err=TIFFReadDirEntryDouble(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + if (!TIFFSetField(tif,dp->tdir_tag,data)) + return(0); + } + } + break; + case TIFF_SETGET_IFD8: + { + uint64 data; + assert(fip->field_readcount==1); + assert(fip->field_passcount==0); + err=TIFFReadDirEntryIfd8(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + if (!TIFFSetField(tif,dp->tdir_tag,data)) + return(0); + } + } + break; + case TIFF_SETGET_UINT16_PAIR: + { + uint16* data; + assert(fip->field_readcount==2); + assert(fip->field_passcount==0); + if (dp->tdir_count!=2) { + TIFFWarningExt(tif->tif_clientdata,module, + "incorrect count for field \"%s\", expected 2, got %d", + fip->field_name,(int)dp->tdir_count); + return(0); + } + err=TIFFReadDirEntryShortArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,data[0],data[1]); + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C0_UINT8: + { + uint8* data; + assert(fip->field_readcount>=1); + assert(fip->field_passcount==0); + if (dp->tdir_count!=(uint64)fip->field_readcount) { + TIFFWarningExt(tif->tif_clientdata,module, + "incorrect count for field \"%s\", expected %d, got %d", + fip->field_name,(int) fip->field_readcount, (int)dp->tdir_count); + return 0; + } + else + { + err=TIFFReadDirEntryByteArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C0_UINT16: + { + uint16* data; + assert(fip->field_readcount>=1); + assert(fip->field_passcount==0); + if (dp->tdir_count!=(uint64)fip->field_readcount) + /* corrupt file */; + else + { + err=TIFFReadDirEntryShortArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C0_UINT32: + { + uint32* data; + assert(fip->field_readcount>=1); + assert(fip->field_passcount==0); + if (dp->tdir_count!=(uint64)fip->field_readcount) + /* corrupt file */; + else + { + err=TIFFReadDirEntryLongArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C0_FLOAT: + { + float* data; + assert(fip->field_readcount>=1); + assert(fip->field_passcount==0); + if (dp->tdir_count!=(uint64)fip->field_readcount) + /* corrupt file */; + else + { + err=TIFFReadDirEntryFloatArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C16_ASCII: + { + uint8* data; + assert(fip->field_readcount==TIFF_VARIABLE); + assert(fip->field_passcount==1); + if (dp->tdir_count>0xFFFF) + err=TIFFReadDirEntryErrCount; + else + { + err=TIFFReadDirEntryByteArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) { - if (data!=NULL) - _TIFFfree(data); - return(0); + TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); + data[dp->tdir_count-1] = '\0'; } - _TIFFmemcpy(o,data,(uint32)dp->tdir_count); - o[(uint32)dp->tdir_count]=0; - if (data!=0) - _TIFFfree(data); - data=o; - } - n=TIFFSetField(tif,dp->tdir_tag,data); - if (data!=0) - _TIFFfree(data); - if (!n) - return(0); - } - } - break; - case TIFF_SETGET_UINT8: - { - uint8 data; - assert(fip->field_readcount==1); - assert(fip->field_passcount==0); - err=TIFFReadDirEntryByte(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - if (!TIFFSetField(tif,dp->tdir_tag,data)) - return(0); - } - } - break; - case TIFF_SETGET_UINT16: - { - uint16 data; - assert(fip->field_readcount==1); - assert(fip->field_passcount==0); - err=TIFFReadDirEntryShort(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - if (!TIFFSetField(tif,dp->tdir_tag,data)) - return(0); - } - } - break; - case TIFF_SETGET_UINT32: - { - uint32 data; - assert(fip->field_readcount==1); - assert(fip->field_passcount==0); - err=TIFFReadDirEntryLong(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - if (!TIFFSetField(tif,dp->tdir_tag,data)) - return(0); - } - } - break; - case TIFF_SETGET_UINT64: - { - uint64 data; - assert(fip->field_readcount==1); - assert(fip->field_passcount==0); - err=TIFFReadDirEntryLong8(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - if (!TIFFSetField(tif,dp->tdir_tag,data)) - return(0); - } - } - break; - case TIFF_SETGET_FLOAT: - { - float data; - assert(fip->field_readcount==1); - assert(fip->field_passcount==0); - err=TIFFReadDirEntryFloat(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - if (!TIFFSetField(tif,dp->tdir_tag,data)) - return(0); - } - } - break; - case TIFF_SETGET_DOUBLE: - { - double data; - assert(fip->field_readcount==1); - assert(fip->field_passcount==0); - err=TIFFReadDirEntryDouble(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - if (!TIFFSetField(tif,dp->tdir_tag,data)) - return(0); - } - } - break; - case TIFF_SETGET_IFD8: - { - uint64 data; - assert(fip->field_readcount==1); - assert(fip->field_passcount==0); - err=TIFFReadDirEntryIfd8(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - if (!TIFFSetField(tif,dp->tdir_tag,data)) - return(0); - } - } - break; - case TIFF_SETGET_UINT16_PAIR: - { - uint16* data; - assert(fip->field_readcount==2); - assert(fip->field_passcount==0); - if (dp->tdir_count!=2) - return(0); - err=TIFFReadDirEntryShortArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,data[0],data[1]); - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C0_UINT8: - { - uint8* data; - assert(fip->field_readcount>=1); - assert(fip->field_passcount==0); - if (dp->tdir_count!=(uint64)fip->field_readcount) - /* corrupt file */; - else - { - err=TIFFReadDirEntryByteArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) + m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C16_UINT8: + { + uint8* data; + assert(fip->field_readcount==TIFF_VARIABLE); + assert(fip->field_passcount==1); + if (dp->tdir_count>0xFFFF) + err=TIFFReadDirEntryErrCount; + else + { + err=TIFFReadDirEntryByteArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C16_UINT16: + { + uint16* data; + assert(fip->field_readcount==TIFF_VARIABLE); + assert(fip->field_passcount==1); + if (dp->tdir_count>0xFFFF) + err=TIFFReadDirEntryErrCount; + else + { + err=TIFFReadDirEntryShortArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C16_UINT32: + { + uint32* data; + assert(fip->field_readcount==TIFF_VARIABLE); + assert(fip->field_passcount==1); + if (dp->tdir_count>0xFFFF) + err=TIFFReadDirEntryErrCount; + else + { + err=TIFFReadDirEntryLongArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C16_UINT64: + { + uint64* data; + assert(fip->field_readcount==TIFF_VARIABLE); + assert(fip->field_passcount==1); + if (dp->tdir_count>0xFFFF) + err=TIFFReadDirEntryErrCount; + else + { + err=TIFFReadDirEntryLong8Array(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C16_FLOAT: + { + float* data; + assert(fip->field_readcount==TIFF_VARIABLE); + assert(fip->field_passcount==1); + if (dp->tdir_count>0xFFFF) + err=TIFFReadDirEntryErrCount; + else + { + err=TIFFReadDirEntryFloatArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C16_DOUBLE: + { + double* data; + assert(fip->field_readcount==TIFF_VARIABLE); + assert(fip->field_passcount==1); + if (dp->tdir_count>0xFFFF) + err=TIFFReadDirEntryErrCount; + else + { + err=TIFFReadDirEntryDoubleArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C16_IFD8: + { + uint64* data; + assert(fip->field_readcount==TIFF_VARIABLE); + assert(fip->field_passcount==1); + if (dp->tdir_count>0xFFFF) + err=TIFFReadDirEntryErrCount; + else + { + err=TIFFReadDirEntryIfd8Array(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + } + break; + case TIFF_SETGET_C32_ASCII: + { + uint8* data; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntryByteArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' ) { - int m; - m=TIFFSetField(tif,dp->tdir_tag,data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); + TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name); + data[dp->tdir_count-1] = '\0'; } - } - } - break; - case TIFF_SETGET_C0_UINT16: - { - uint16* data; - assert(fip->field_readcount>=1); - assert(fip->field_passcount==0); - if (dp->tdir_count!=(uint64)fip->field_readcount) - /* corrupt file */; - else - { - err=TIFFReadDirEntryShortArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - } - break; - case TIFF_SETGET_C0_UINT32: - { - uint32* data; - assert(fip->field_readcount>=1); - assert(fip->field_passcount==0); - if (dp->tdir_count!=(uint64)fip->field_readcount) - /* corrupt file */; - else - { - err=TIFFReadDirEntryLongArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - } - break; - case TIFF_SETGET_C0_FLOAT: - { - float* data; - assert(fip->field_readcount>=1); - assert(fip->field_passcount==0); - if (dp->tdir_count!=(uint64)fip->field_readcount) - /* corrupt file */; - else - { - err=TIFFReadDirEntryFloatArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - } - break; - case TIFF_SETGET_C16_ASCII: - { - uint8* data; - assert(fip->field_readcount==TIFF_VARIABLE); - assert(fip->field_passcount==1); - if (dp->tdir_count>0xFFFF) - err=TIFFReadDirEntryErrCount; - else - { - err=TIFFReadDirEntryByteArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - } - break; - case TIFF_SETGET_C16_UINT8: - { - uint8* data; - assert(fip->field_readcount==TIFF_VARIABLE); - assert(fip->field_passcount==1); - if (dp->tdir_count>0xFFFF) - err=TIFFReadDirEntryErrCount; - else - { - err=TIFFReadDirEntryByteArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - } - break; - case TIFF_SETGET_C16_UINT16: - { - uint16* data; - assert(fip->field_readcount==TIFF_VARIABLE); - assert(fip->field_passcount==1); - if (dp->tdir_count>0xFFFF) - err=TIFFReadDirEntryErrCount; - else - { - err=TIFFReadDirEntryShortArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - } - break; - case TIFF_SETGET_C16_UINT32: - { - uint32* data; - assert(fip->field_readcount==TIFF_VARIABLE); - assert(fip->field_passcount==1); - if (dp->tdir_count>0xFFFF) - err=TIFFReadDirEntryErrCount; - else - { - err=TIFFReadDirEntryLongArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - } - break; - case TIFF_SETGET_C16_UINT64: - { - uint64* data; - assert(fip->field_readcount==TIFF_VARIABLE); - assert(fip->field_passcount==1); - if (dp->tdir_count>0xFFFF) - err=TIFFReadDirEntryErrCount; - else - { - err=TIFFReadDirEntryLong8Array(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - } - break; - case TIFF_SETGET_C16_FLOAT: - { - float* data; - assert(fip->field_readcount==TIFF_VARIABLE); - assert(fip->field_passcount==1); - if (dp->tdir_count>0xFFFF) - err=TIFFReadDirEntryErrCount; - else - { - err=TIFFReadDirEntryFloatArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - } - break; - case TIFF_SETGET_C16_DOUBLE: - { - double* data; - assert(fip->field_readcount==TIFF_VARIABLE); - assert(fip->field_passcount==1); - if (dp->tdir_count>0xFFFF) - err=TIFFReadDirEntryErrCount; - else - { - err=TIFFReadDirEntryDoubleArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - } - break; - case TIFF_SETGET_C16_IFD8: - { - uint64* data; - assert(fip->field_readcount==TIFF_VARIABLE); - assert(fip->field_passcount==1); - if (dp->tdir_count>0xFFFF) - err=TIFFReadDirEntryErrCount; - else - { - err=TIFFReadDirEntryIfd8Array(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - } - break; - case TIFF_SETGET_C32_ASCII: - { - uint8* data; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntryByteArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C32_UINT8: - { - uint8* data; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntryByteArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C32_SINT8: - { - int8* data = NULL; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntrySbyteArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C32_UINT16: - { - uint16* data; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntryShortArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C32_SINT16: - { - int16* data = NULL; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntrySshortArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C32_UINT32: - { - uint32* data; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntryLongArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C32_SINT32: - { - int32* data = NULL; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntrySlongArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C32_UINT64: - { - uint64* data; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntryLong8Array(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C32_SINT64: - { - int64* data = NULL; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntrySlong8Array(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C32_FLOAT: - { - float* data; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntryFloatArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C32_DOUBLE: - { - double* data; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntryDoubleArray(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - case TIFF_SETGET_C32_IFD8: - { - uint64* data; - assert(fip->field_readcount==TIFF_VARIABLE2); - assert(fip->field_passcount==1); - err=TIFFReadDirEntryIfd8Array(tif,dp,&data); - if (err==TIFFReadDirEntryErrOk) - { - int m; - m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); - if (data!=0) - _TIFFfree(data); - if (!m) - return(0); - } - } - break; - default: - assert(0); /* we should never get here */ - break; - } - if (err!=TIFFReadDirEntryErrOk) - { - TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",recover); - return(0); - } - return(1); + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C32_UINT8: + { + uint8* data; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntryByteArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C32_SINT8: + { + int8* data = NULL; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntrySbyteArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C32_UINT16: + { + uint16* data; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntryShortArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C32_SINT16: + { + int16* data = NULL; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntrySshortArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C32_UINT32: + { + uint32* data; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntryLongArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C32_SINT32: + { + int32* data = NULL; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntrySlongArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C32_UINT64: + { + uint64* data; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntryLong8Array(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C32_SINT64: + { + int64* data = NULL; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntrySlong8Array(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C32_FLOAT: + { + float* data; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntryFloatArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C32_DOUBLE: + { + double* data; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntryDoubleArray(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + case TIFF_SETGET_C32_IFD8: + { + uint64* data; + assert(fip->field_readcount==TIFF_VARIABLE2); + assert(fip->field_passcount==1); + err=TIFFReadDirEntryIfd8Array(tif,dp,&data); + if (err==TIFFReadDirEntryErrOk) + { + int m; + m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data); + if (data!=0) + _TIFFfree(data); + if (!m) + return(0); + } + } + break; + default: + assert(0); /* we should never get here */ + break; + } + if (err!=TIFFReadDirEntryErrOk) + { + TIFFReadDirEntryOutputErr(tif,err,module,fip->field_name,recover); + return(0); + } + return(1); } /* @@ -5355,36 +5537,47 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover) static int TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp) { - static const char module[] = "TIFFFetchStripThing"; - enum TIFFReadDirEntryErr err; - uint64* data; - err=TIFFReadDirEntryLong8Array(tif,dir,&data); - if (err!=TIFFReadDirEntryErrOk) - { - const TIFFField* fip = TIFFFieldWithTag(tif,dir->tdir_tag); - TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); - return(0); - } - if (dir->tdir_count!=(uint64)nstrips) - { - uint64* resizeddata; - resizeddata=(uint64*)_TIFFCheckMalloc(tif,nstrips,sizeof(uint64),"for strip array"); - if (resizeddata==0) { - _TIFFfree(data); - return(0); - } - if (dir->tdir_count<(uint64)nstrips) - { - _TIFFmemcpy(resizeddata,data,(uint32)dir->tdir_count*sizeof(uint64)); - _TIFFmemset(resizeddata+(uint32)dir->tdir_count,0,(nstrips-(uint32)dir->tdir_count)*sizeof(uint64)); - } - else - _TIFFmemcpy(resizeddata,data,nstrips*sizeof(uint64)); - _TIFFfree(data); - data=resizeddata; - } - *lpp=data; - return(1); + static const char module[] = "TIFFFetchStripThing"; + enum TIFFReadDirEntryErr err; + uint64* data; + err=TIFFReadDirEntryLong8ArrayWithLimit(tif,dir,&data,nstrips); + if (err!=TIFFReadDirEntryErrOk) + { + const TIFFField* fip = TIFFFieldWithTag(tif,dir->tdir_tag); + TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); + return(0); + } + if (dir->tdir_count<(uint64)nstrips) + { + uint64* resizeddata; + const TIFFField* fip = TIFFFieldWithTag(tif,dir->tdir_tag); + const char* pszMax = getenv("LIBTIFF_STRILE_ARRAY_MAX_RESIZE_COUNT"); + uint32 max_nstrips = 1000000; + if( pszMax ) + max_nstrips = (uint32) atoi(pszMax); + TIFFReadDirEntryOutputErr(tif,TIFFReadDirEntryErrCount, + module, + fip ? fip->field_name : "unknown tagname", + ( nstrips <= max_nstrips ) ); + + if( nstrips > max_nstrips ) + { + _TIFFfree(data); + return(0); + } + + resizeddata=(uint64*)_TIFFCheckMalloc(tif,nstrips,sizeof(uint64),"for strip array"); + if (resizeddata==0) { + _TIFFfree(data); + return(0); + } + _TIFFmemcpy(resizeddata,data,(uint32)dir->tdir_count*sizeof(uint64)); + _TIFFmemset(resizeddata+(uint32)dir->tdir_count,0,(nstrips-(uint32)dir->tdir_count)*sizeof(uint64)); + _TIFFfree(data); + data=resizeddata; + } + *lpp=data; + return(1); } /* @@ -5393,56 +5586,56 @@ TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp) static int TIFFFetchSubjectDistance(TIFF* tif, TIFFDirEntry* dir) { - static const char module[] = "TIFFFetchSubjectDistance"; - enum TIFFReadDirEntryErr err; - UInt64Aligned_t m; + static const char module[] = "TIFFFetchSubjectDistance"; + enum TIFFReadDirEntryErr err; + UInt64Aligned_t m; m.l=0; - assert(sizeof(double)==8); - assert(sizeof(uint64)==8); - assert(sizeof(uint32)==4); - if (dir->tdir_count!=1) - err=TIFFReadDirEntryErrCount; - else if (dir->tdir_type!=TIFF_RATIONAL) - err=TIFFReadDirEntryErrType; - else - { - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - uint32 offset; - offset=*(uint32*)(&dir->tdir_offset); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&offset); - err=TIFFReadDirEntryData(tif,offset,8,m.i); - } - else - { - m.l=dir->tdir_offset.toff_long8; - err=TIFFReadDirEntryErrOk; - } - } - if (err==TIFFReadDirEntryErrOk) - { - double n; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong(m.i,2); - if (m.i[0]==0) - n=0.0; - else if (m.i[0]==0xFFFFFFFF) - /* - * XXX: Numerator 0xFFFFFFFF means that we have infinite - * distance. Indicate that with a negative floating point - * SubjectDistance value. - */ - n=-1.0; - else - n=(double)m.i[0]/(double)m.i[1]; - return(TIFFSetField(tif,dir->tdir_tag,n)); - } - else - { - TIFFReadDirEntryOutputErr(tif,err,module,"SubjectDistance",TRUE); - return(0); - } + assert(sizeof(double)==8); + assert(sizeof(uint64)==8); + assert(sizeof(uint32)==4); + if (dir->tdir_count!=1) + err=TIFFReadDirEntryErrCount; + else if (dir->tdir_type!=TIFF_RATIONAL) + err=TIFFReadDirEntryErrType; + else + { + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + uint32 offset; + offset=*(uint32*)(&dir->tdir_offset); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&offset); + err=TIFFReadDirEntryData(tif,offset,8,m.i); + } + else + { + m.l=dir->tdir_offset.toff_long8; + err=TIFFReadDirEntryErrOk; + } + } + if (err==TIFFReadDirEntryErrOk) + { + double n; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong(m.i,2); + if (m.i[0]==0) + n=0.0; + else if (m.i[0]==0xFFFFFFFF) + /* + * XXX: Numerator 0xFFFFFFFF means that we have infinite + * distance. Indicate that with a negative floating point + * SubjectDistance value. + */ + n=-1.0; + else + n=(double)m.i[0]/(double)m.i[1]; + return(TIFFSetField(tif,dir->tdir_tag,n)); + } + else + { + TIFFReadDirEntryOutputErr(tif,err,module,"SubjectDistance",TRUE); + return(0); + } } /* @@ -5454,95 +5647,103 @@ TIFFFetchSubjectDistance(TIFF* tif, TIFFDirEntry* dir) static void ChopUpSingleUncompressedStrip(TIFF* tif) { - register TIFFDirectory *td = &tif->tif_dir; - uint64 bytecount; - uint64 offset; - uint32 rowblock; - uint64 rowblockbytes; - uint64 stripbytes; - uint32 strip; - uint64 nstrips64; - uint32 nstrips32; - uint32 rowsperstrip; - uint64* newcounts; - uint64* newoffsets; + register TIFFDirectory *td = &tif->tif_dir; + uint64 bytecount; + uint64 offset; + uint32 rowblock; + uint64 rowblockbytes; + uint64 stripbytes; + uint32 strip; + uint32 nstrips; + uint32 rowsperstrip; + uint64* newcounts; + uint64* newoffsets; - bytecount = td->td_stripbytecount[0]; - offset = td->td_stripoffset[0]; - assert(td->td_planarconfig == PLANARCONFIG_CONTIG); - if ((td->td_photometric == PHOTOMETRIC_YCBCR)&& - (!isUpSampled(tif))) - rowblock = td->td_ycbcrsubsampling[1]; - else - rowblock = 1; - rowblockbytes = TIFFVTileSize64(tif, rowblock); - /* - * Make the rows hold at least one scanline, but fill specified amount - * of data if possible. - */ - if (rowblockbytes > STRIP_SIZE_DEFAULT) { - stripbytes = rowblockbytes; - rowsperstrip = rowblock; - } else if (rowblockbytes > 0 ) { - uint32 rowblocksperstrip; - rowblocksperstrip = (uint32) (STRIP_SIZE_DEFAULT / rowblockbytes); - rowsperstrip = rowblocksperstrip * rowblock; - stripbytes = rowblocksperstrip * rowblockbytes; - } - else - return; + bytecount = td->td_stripbytecount[0]; + /* On a newly created file, just re-opened to be filled, we */ + /* don't want strip chop to trigger as it is going to cause issues */ + /* later ( StripOffsets and StripByteCounts improperly filled) . */ + if( bytecount == 0 && tif->tif_mode != O_RDONLY ) + return; + offset = td->td_stripoffset[0]; + assert(td->td_planarconfig == PLANARCONFIG_CONTIG); + if ((td->td_photometric == PHOTOMETRIC_YCBCR)&& + (!isUpSampled(tif))) + rowblock = td->td_ycbcrsubsampling[1]; + else + rowblock = 1; + rowblockbytes = TIFFVTileSize64(tif, rowblock); + /* + * Make the rows hold at least one scanline, but fill specified amount + * of data if possible. + */ + if (rowblockbytes > STRIP_SIZE_DEFAULT) { + stripbytes = rowblockbytes; + rowsperstrip = rowblock; + } else if (rowblockbytes > 0 ) { + uint32 rowblocksperstrip; + rowblocksperstrip = (uint32) (STRIP_SIZE_DEFAULT / rowblockbytes); + rowsperstrip = rowblocksperstrip * rowblock; + stripbytes = rowblocksperstrip * rowblockbytes; + } + else + return; - /* - * never increase the number of strips in an image - */ - if (rowsperstrip >= td->td_rowsperstrip) - return; - nstrips64 = TIFFhowmany_64(bytecount, stripbytes); - if ((nstrips64==0)||(nstrips64>0xFFFFFFFF)) /* something is wonky, do nothing. */ - return; - nstrips32 = (uint32)nstrips64; + /* + * never increase the number of rows per strip + */ + if (rowsperstrip >= td->td_rowsperstrip) + return; + nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip); + if( nstrips == 0 ) + return; - newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips32, sizeof (uint64), - "for chopped \"StripByteCounts\" array"); - newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips32, sizeof (uint64), - "for chopped \"StripOffsets\" array"); - if (newcounts == NULL || newoffsets == NULL) { - /* - * Unable to allocate new strip information, give up and use - * the original one strip information. - */ - if (newcounts != NULL) - _TIFFfree(newcounts); - if (newoffsets != NULL) - _TIFFfree(newoffsets); - return; - } - /* - * Fill the strip information arrays with new bytecounts and offsets - * that reflect the broken-up format. - */ - for (strip = 0; strip < nstrips32; strip++) { - if (stripbytes > bytecount) - stripbytes = bytecount; - newcounts[strip] = stripbytes; - newoffsets[strip] = offset; - offset += stripbytes; - bytecount -= stripbytes; - } - /* - * Replace old single strip info with multi-strip info. - */ - td->td_stripsperimage = td->td_nstrips = nstrips32; - TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); + newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), + "for chopped \"StripByteCounts\" array"); + newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), + "for chopped \"StripOffsets\" array"); + if (newcounts == NULL || newoffsets == NULL) { + /* + * Unable to allocate new strip information, give up and use + * the original one strip information. + */ + if (newcounts != NULL) + _TIFFfree(newcounts); + if (newoffsets != NULL) + _TIFFfree(newoffsets); + return; + } + /* + * Fill the strip information arrays with new bytecounts and offsets + * that reflect the broken-up format. + */ + for (strip = 0; strip < nstrips; strip++) { + if (stripbytes > bytecount) + stripbytes = bytecount; + newcounts[strip] = stripbytes; + newoffsets[strip] = stripbytes ? offset : 0; + offset += stripbytes; + bytecount -= stripbytes; + } + /* + * Replace old single strip info with multi-strip info. + */ + td->td_stripsperimage = td->td_nstrips = nstrips; + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); - _TIFFfree(td->td_stripbytecount); - _TIFFfree(td->td_stripoffset); - td->td_stripbytecount = newcounts; - td->td_stripoffset = newoffsets; - td->td_stripbytecountsorted = 1; + _TIFFfree(td->td_stripbytecount); + _TIFFfree(td->td_stripoffset); + td->td_stripbytecount = newcounts; + td->td_stripoffset = newoffsets; + td->td_stripbytecountsorted = 1; } int _TIFFFillStriles( TIFF *tif ) +{ + return _TIFFFillStrilesInternal( tif, 1 ); +} + +static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount ) { #if defined(DEFER_STRILE_LOAD) register TIFFDirectory *td = &tif->tif_dir; @@ -5560,7 +5761,8 @@ int _TIFFFillStriles( TIFF *tif ) return_value = 0; } - if (!TIFFFetchStripThing(tif,&(td->td_stripbytecount_entry), + if (loadStripByteCount && + !TIFFFetchStripThing(tif,&(td->td_stripbytecount_entry), td->td_nstrips,&td->td_stripbytecount)) { return_value = 0; @@ -5569,24 +5771,25 @@ int _TIFFFillStriles( TIFF *tif ) _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry)); _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry)); - if (tif->tif_dir.td_nstrips > 1 && return_value == 1 ) { - uint32 strip; + if (tif->tif_dir.td_nstrips > 1 && return_value == 1 ) { + uint32 strip; - tif->tif_dir.td_stripbytecountsorted = 1; - for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) { - if (tif->tif_dir.td_stripoffset[strip - 1] > - tif->tif_dir.td_stripoffset[strip]) { - tif->tif_dir.td_stripbytecountsorted = 0; - break; - } - } - } + tif->tif_dir.td_stripbytecountsorted = 1; + for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) { + if (tif->tif_dir.td_stripoffset[strip - 1] > + tif->tif_dir.td_stripoffset[strip]) { + tif->tif_dir.td_stripbytecountsorted = 0; + break; + } + } + } return return_value; #else /* !defined(DEFER_STRILE_LOAD) */ (void) tif; + (void) loadStripByteCount; return 1; -#endif +#endif } diff --git a/3rdparty/libtiff/tif_dirwrite.c b/3rdparty/libtiff/tif_dirwrite.c index 35adb60bc1..c68d6d21d6 100644 --- a/3rdparty/libtiff/tif_dirwrite.c +++ b/3rdparty/libtiff/tif_dirwrite.c @@ -1,4 +1,4 @@ -/* $Id: tif_dirwrite.c,v 1.76 2011-02-18 20:53:04 fwarmerdam Exp $ */ +/* $Id: tif_dirwrite.c,v 1.89 2017-08-23 13:33:42 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -30,6 +30,7 @@ * Directory Write Support Routines. */ #include "tiffiop.h" +#include #ifdef HAVE_IEEEFP #define TIFFCvtNativeToIEEEFloat(tif, n, fp) @@ -180,7 +181,7 @@ static int TIFFLinkDirectory(TIFF*); int TIFFWriteDirectory(TIFF* tif) { - return TIFFWriteDirectorySec(tif,TRUE,TRUE,NULL); + return TIFFWriteDirectorySec(tif,TRUE,TRUE,NULL); } /* @@ -192,917 +193,999 @@ TIFFWriteDirectory(TIFF* tif) int TIFFCheckpointDirectory(TIFF* tif) { - int rc; - /* Setup the strips arrays, if they haven't already been. */ - if (tif->tif_dir.td_stripoffset == NULL) - (void) TIFFSetupStrips(tif); - rc = TIFFWriteDirectorySec(tif,TRUE,FALSE,NULL); - (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END)); - return rc; + int rc; + /* Setup the strips arrays, if they haven't already been. */ + if (tif->tif_dir.td_stripoffset == NULL) + (void) TIFFSetupStrips(tif); + rc = TIFFWriteDirectorySec(tif,TRUE,FALSE,NULL); + (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END)); + return rc; } int TIFFWriteCustomDirectory(TIFF* tif, uint64* pdiroff) { - return TIFFWriteDirectorySec(tif,FALSE,FALSE,pdiroff); + return TIFFWriteDirectorySec(tif,FALSE,FALSE,pdiroff); } /* * Similar to TIFFWriteDirectory(), but if the directory has already * been written once, it is relocated to the end of the file, in case it * has changed in size. Note that this will result in the loss of the - * previously used directory space. - */ + * previously used directory space. + */ int TIFFRewriteDirectory( TIFF *tif ) { - static const char module[] = "TIFFRewriteDirectory"; + static const char module[] = "TIFFRewriteDirectory"; - /* We don't need to do anything special if it hasn't been written. */ - if( tif->tif_diroff == 0 ) - return TIFFWriteDirectory( tif ); + /* We don't need to do anything special if it hasn't been written. */ + if( tif->tif_diroff == 0 ) + return TIFFWriteDirectory( tif ); - /* - * Find and zero the pointer to this directory, so that TIFFLinkDirectory - * will cause it to be added after this directories current pre-link. - */ + /* + * Find and zero the pointer to this directory, so that TIFFLinkDirectory + * will cause it to be added after this directories current pre-link. + */ - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - if (tif->tif_header.classic.tiff_diroff == tif->tif_diroff) - { - tif->tif_header.classic.tiff_diroff = 0; - tif->tif_diroff = 0; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + if (tif->tif_header.classic.tiff_diroff == tif->tif_diroff) + { + tif->tif_header.classic.tiff_diroff = 0; + tif->tif_diroff = 0; - TIFFSeekFile(tif,4,SEEK_SET); - if (!WriteOK(tif, &(tif->tif_header.classic.tiff_diroff),4)) - { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "Error updating TIFF header"); - return (0); - } - } - else - { - uint32 nextdir; - nextdir = tif->tif_header.classic.tiff_diroff; - while(1) { - uint16 dircount; - uint32 nextnextdir; + TIFFSeekFile(tif,4,SEEK_SET); + if (!WriteOK(tif, &(tif->tif_header.classic.tiff_diroff),4)) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error updating TIFF header"); + return (0); + } + } + else + { + uint32 nextdir; + nextdir = tif->tif_header.classic.tiff_diroff; + while(1) { + uint16 dircount; + uint32 nextnextdir; - if (!SeekOK(tif, nextdir) || - !ReadOK(tif, &dircount, 2)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error fetching directory count"); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabShort(&dircount); - (void) TIFFSeekFile(tif, - nextdir+2+dircount*12, SEEK_SET); - if (!ReadOK(tif, &nextnextdir, 4)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error fetching directory link"); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong(&nextnextdir); - if (nextnextdir==tif->tif_diroff) - { - uint32 m; - m=0; - (void) TIFFSeekFile(tif, - nextdir+2+dircount*12, SEEK_SET); - if (!WriteOK(tif, &m, 4)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error writing directory link"); - return (0); - } - tif->tif_diroff=0; - break; - } - nextdir=nextnextdir; - } - } - } - else - { - if (tif->tif_header.big.tiff_diroff == tif->tif_diroff) - { - tif->tif_header.big.tiff_diroff = 0; - tif->tif_diroff = 0; + if (!SeekOK(tif, nextdir) || + !ReadOK(tif, &dircount, 2)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory count"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + (void) TIFFSeekFile(tif, + nextdir+2+dircount*12, SEEK_SET); + if (!ReadOK(tif, &nextnextdir, 4)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory link"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&nextnextdir); + if (nextnextdir==tif->tif_diroff) + { + uint32 m; + m=0; + (void) TIFFSeekFile(tif, + nextdir+2+dircount*12, SEEK_SET); + if (!WriteOK(tif, &m, 4)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error writing directory link"); + return (0); + } + tif->tif_diroff=0; + break; + } + nextdir=nextnextdir; + } + } + } + else + { + if (tif->tif_header.big.tiff_diroff == tif->tif_diroff) + { + tif->tif_header.big.tiff_diroff = 0; + tif->tif_diroff = 0; - TIFFSeekFile(tif,8,SEEK_SET); - if (!WriteOK(tif, &(tif->tif_header.big.tiff_diroff),8)) - { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "Error updating TIFF header"); - return (0); - } - } - else - { - uint64 nextdir; - nextdir = tif->tif_header.big.tiff_diroff; - while(1) { - uint64 dircount64; - uint16 dircount; - uint64 nextnextdir; + TIFFSeekFile(tif,8,SEEK_SET); + if (!WriteOK(tif, &(tif->tif_header.big.tiff_diroff),8)) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error updating TIFF header"); + return (0); + } + } + else + { + uint64 nextdir; + nextdir = tif->tif_header.big.tiff_diroff; + while(1) { + uint64 dircount64; + uint16 dircount; + uint64 nextnextdir; - if (!SeekOK(tif, nextdir) || - !ReadOK(tif, &dircount64, 8)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error fetching directory count"); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(&dircount64); - if (dircount64>0xFFFF) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Sanity check on tag count failed, likely corrupt TIFF"); - return (0); - } - dircount=(uint16)dircount64; - (void) TIFFSeekFile(tif, - nextdir+8+dircount*20, SEEK_SET); - if (!ReadOK(tif, &nextnextdir, 8)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error fetching directory link"); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(&nextnextdir); - if (nextnextdir==tif->tif_diroff) - { - uint64 m; - m=0; - (void) TIFFSeekFile(tif, - nextdir+8+dircount*20, SEEK_SET); - if (!WriteOK(tif, &m, 8)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error writing directory link"); - return (0); - } - tif->tif_diroff=0; - break; - } - nextdir=nextnextdir; - } - } - } + if (!SeekOK(tif, nextdir) || + !ReadOK(tif, &dircount64, 8)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory count"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8(&dircount64); + if (dircount64>0xFFFF) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Sanity check on tag count failed, likely corrupt TIFF"); + return (0); + } + dircount=(uint16)dircount64; + (void) TIFFSeekFile(tif, + nextdir+8+dircount*20, SEEK_SET); + if (!ReadOK(tif, &nextnextdir, 8)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory link"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8(&nextnextdir); + if (nextnextdir==tif->tif_diroff) + { + uint64 m; + m=0; + (void) TIFFSeekFile(tif, + nextdir+8+dircount*20, SEEK_SET); + if (!WriteOK(tif, &m, 8)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error writing directory link"); + return (0); + } + tif->tif_diroff=0; + break; + } + nextdir=nextnextdir; + } + } + } - /* - * Now use TIFFWriteDirectory() normally. - */ + /* + * Now use TIFFWriteDirectory() normally. + */ - return TIFFWriteDirectory( tif ); + return TIFFWriteDirectory( tif ); } static int TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) { - static const char module[] = "TIFFWriteDirectorySec"; - uint32 ndir; - TIFFDirEntry* dir; - uint32 dirsize; - void* dirmem; - uint32 m; - if (tif->tif_mode == O_RDONLY) - return (1); + static const char module[] = "TIFFWriteDirectorySec"; + uint32 ndir; + TIFFDirEntry* dir; + uint32 dirsize; + void* dirmem; + uint32 m; + if (tif->tif_mode == O_RDONLY) + return (1); _TIFFFillStriles( tif ); - - /* - * Clear write state so that subsequent images with - * different characteristics get the right buffers - * setup for them. - */ - if (imagedone) - { - if (tif->tif_flags & TIFF_POSTENCODE) - { - tif->tif_flags &= ~TIFF_POSTENCODE; - if (!(*tif->tif_postencode)(tif)) - { - TIFFErrorExt(tif->tif_clientdata,module, - "Error post-encoding before directory write"); - return (0); - } - } - (*tif->tif_close)(tif); /* shutdown encoder */ - /* - * Flush any data that might have been written - * by the compression close+cleanup routines. But + + /* + * Clear write state so that subsequent images with + * different characteristics get the right buffers + * setup for them. + */ + if (imagedone) + { + if (tif->tif_flags & TIFF_POSTENCODE) + { + tif->tif_flags &= ~TIFF_POSTENCODE; + if (!(*tif->tif_postencode)(tif)) + { + TIFFErrorExt(tif->tif_clientdata,module, + "Error post-encoding before directory write"); + return (0); + } + } + (*tif->tif_close)(tif); /* shutdown encoder */ + /* + * Flush any data that might have been written + * by the compression close+cleanup routines. But * be careful not to write stuff if we didn't add data * in the previous steps as the "rawcc" data may well be * a previously read tile/strip in mixed read/write mode. - */ - if (tif->tif_rawcc > 0 - && (tif->tif_flags & TIFF_BEENWRITING) != 0 ) - { - if( !TIFFFlushData1(tif) ) + */ + if (tif->tif_rawcc > 0 + && (tif->tif_flags & TIFF_BEENWRITING) != 0 ) + { + if( !TIFFFlushData1(tif) ) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error flushing data before directory write"); - return (0); + TIFFErrorExt(tif->tif_clientdata, module, + "Error flushing data before directory write"); + return (0); } - } - if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) - { - _TIFFfree(tif->tif_rawdata); - tif->tif_rawdata = NULL; - tif->tif_rawcc = 0; - tif->tif_rawdatasize = 0; + } + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) + { + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = NULL; + tif->tif_rawcc = 0; + tif->tif_rawdatasize = 0; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = 0; - } - tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP); - } - dir=NULL; - dirmem=NULL; - dirsize=0; - while (1) - { - ndir=0; - if (isimage) - { - if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) - { - if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_IMAGEWIDTH,tif->tif_dir.td_imagewidth)) - goto bad; - if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_IMAGELENGTH,tif->tif_dir.td_imagelength)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) - { - if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_TILEWIDTH,tif->tif_dir.td_tilewidth)) - goto bad; - if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_TILELENGTH,tif->tif_dir.td_tilelength)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_RESOLUTION)) - { - if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_XRESOLUTION,tif->tif_dir.td_xresolution)) - goto bad; - if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_YRESOLUTION,tif->tif_dir.td_yresolution)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_POSITION)) - { - if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_XPOSITION,tif->tif_dir.td_xposition)) - goto bad; - if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_YPOSITION,tif->tif_dir.td_yposition)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) - { - if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_SUBFILETYPE,tif->tif_dir.td_subfiletype)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) - { - if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_BITSPERSAMPLE,tif->tif_dir.td_bitspersample)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_COMPRESSION)) - { - if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_COMPRESSION,tif->tif_dir.td_compression)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) - { - if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_PHOTOMETRIC,tif->tif_dir.td_photometric)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) - { - if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_THRESHHOLDING,tif->tif_dir.td_threshholding)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_FILLORDER)) - { - if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_FILLORDER,tif->tif_dir.td_fillorder)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_ORIENTATION)) - { - if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_ORIENTATION,tif->tif_dir.td_orientation)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) - { - if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_SAMPLESPERPIXEL,tif->tif_dir.td_samplesperpixel)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) - { - if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_ROWSPERSTRIP,tif->tif_dir.td_rowsperstrip)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE)) - { - if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_MINSAMPLEVALUE,tif->tif_dir.td_minsamplevalue)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) - { - if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_MAXSAMPLEVALUE,tif->tif_dir.td_maxsamplevalue)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) - { - if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_PLANARCONFIG,tif->tif_dir.td_planarconfig)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) - { - if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_RESOLUTIONUNIT,tif->tif_dir.td_resolutionunit)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_PAGENUMBER)) - { - if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_PAGENUMBER,2,&tif->tif_dir.td_pagenumber[0])) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_STRIPBYTECOUNTS)) - { - if (!isTiled(tif)) - { - if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount)) + } + tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP); + } + dir=NULL; + dirmem=NULL; + dirsize=0; + while (1) + { + ndir=0; + if (isimage) + { + if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) + { + if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_IMAGEWIDTH,tif->tif_dir.td_imagewidth)) + goto bad; + if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_IMAGELENGTH,tif->tif_dir.td_imagelength)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) + { + if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_TILEWIDTH,tif->tif_dir.td_tilewidth)) + goto bad; + if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_TILELENGTH,tif->tif_dir.td_tilelength)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_RESOLUTION)) + { + if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_XRESOLUTION,tif->tif_dir.td_xresolution)) + goto bad; + if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_YRESOLUTION,tif->tif_dir.td_yresolution)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_POSITION)) + { + if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_XPOSITION,tif->tif_dir.td_xposition)) + goto bad; + if (!TIFFWriteDirectoryTagRational(tif,&ndir,dir,TIFFTAG_YPOSITION,tif->tif_dir.td_yposition)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) + { + if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_SUBFILETYPE,tif->tif_dir.td_subfiletype)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) + { + if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_BITSPERSAMPLE,tif->tif_dir.td_bitspersample)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_COMPRESSION)) + { + if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_COMPRESSION,tif->tif_dir.td_compression)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) + { + if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_PHOTOMETRIC,tif->tif_dir.td_photometric)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) + { + if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_THRESHHOLDING,tif->tif_dir.td_threshholding)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_FILLORDER)) + { + if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_FILLORDER,tif->tif_dir.td_fillorder)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_ORIENTATION)) + { + if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_ORIENTATION,tif->tif_dir.td_orientation)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) + { + if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_SAMPLESPERPIXEL,tif->tif_dir.td_samplesperpixel)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) + { + if (!TIFFWriteDirectoryTagShortLong(tif,&ndir,dir,TIFFTAG_ROWSPERSTRIP,tif->tif_dir.td_rowsperstrip)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE)) + { + if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_MINSAMPLEVALUE,tif->tif_dir.td_minsamplevalue)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) + { + if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_MAXSAMPLEVALUE,tif->tif_dir.td_maxsamplevalue)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) + { + if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_PLANARCONFIG,tif->tif_dir.td_planarconfig)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) + { + if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_RESOLUTIONUNIT,tif->tif_dir.td_resolutionunit)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_PAGENUMBER)) + { + if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_PAGENUMBER,2,&tif->tif_dir.td_pagenumber[0])) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_STRIPBYTECOUNTS)) + { + if (!isTiled(tif)) + { + if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount)) + goto bad; + } + else + { + if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount)) + goto bad; + } + } + if (TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) + { + if (!isTiled(tif)) + { + /* td_stripoffset might be NULL in an odd OJPEG case. See + * tif_dirread.c around line 3634. + * XXX: OJPEG hack. + * If a) compression is OJPEG, b) it's not a tiled TIFF, + * and c) the number of strips is 1, + * then we tolerate the absence of stripoffsets tag, + * because, presumably, all required data is in the + * JpegInterchangeFormat stream. + * We can get here when using tiffset on such a file. + * See http://bugzilla.maptools.org/show_bug.cgi?id=2500 + */ + if (tif->tif_dir.td_stripoffset != NULL && + !TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) goto bad; - } - else - { - if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount)) - goto bad; - } - } - if (TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) - { - if (!isTiled(tif)) - { - if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) - goto bad; - } - else - { - if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) - goto bad; - } - } - if (TIFFFieldSet(tif,FIELD_COLORMAP)) - { - if (!TIFFWriteDirectoryTagColormap(tif,&ndir,dir)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES)) - { - if (tif->tif_dir.td_extrasamples) - { - uint16 na; - uint16* nb; - TIFFGetFieldDefaulted(tif,TIFFTAG_EXTRASAMPLES,&na,&nb); - if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_EXTRASAMPLES,na,nb)) - goto bad; - } - } - if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) - { - if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_SAMPLEFORMAT,tif->tif_dir.td_sampleformat)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) - { - if (!TIFFWriteDirectoryTagSampleformatArray(tif,&ndir,dir,TIFFTAG_SMINSAMPLEVALUE,tif->tif_dir.td_samplesperpixel,tif->tif_dir.td_sminsamplevalue)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) - { - if (!TIFFWriteDirectoryTagSampleformatArray(tif,&ndir,dir,TIFFTAG_SMAXSAMPLEVALUE,tif->tif_dir.td_samplesperpixel,tif->tif_dir.td_smaxsamplevalue)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH)) - { - if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_IMAGEDEPTH,tif->tif_dir.td_imagedepth)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_TILEDEPTH)) - { - if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_TILEDEPTH,tif->tif_dir.td_tiledepth)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS)) - { - if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_HALFTONEHINTS,2,&tif->tif_dir.td_halftonehints[0])) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING)) - { - if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_YCBCRSUBSAMPLING,2,&tif->tif_dir.td_ycbcrsubsampling[0])) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) - { - if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_YCBCRPOSITIONING,tif->tif_dir.td_ycbcrpositioning)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) - { - if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,TIFFTAG_REFERENCEBLACKWHITE,6,tif->tif_dir.td_refblackwhite)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) - { - if (!TIFFWriteDirectoryTagTransferfunction(tif,&ndir,dir)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_INKNAMES)) - { - if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,TIFFTAG_INKNAMES,tif->tif_dir.td_inknameslen,tif->tif_dir.td_inknames)) - goto bad; - } - if (TIFFFieldSet(tif,FIELD_SUBIFD)) - { - if (!TIFFWriteDirectoryTagSubifd(tif,&ndir,dir)) - goto bad; - } - { - uint32 n; - for (n=0; ntif_nfields; n++) { - const TIFFField* o; - o = tif->tif_fields[n]; - if ((o->field_bit>=FIELD_CODEC)&&(TIFFFieldSet(tif,o->field_bit))) - { - switch (o->get_field_type) - { - case TIFF_SETGET_ASCII: + } + else + { + if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) + goto bad; + } + } + if (TIFFFieldSet(tif,FIELD_COLORMAP)) + { + if (!TIFFWriteDirectoryTagColormap(tif,&ndir,dir)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES)) + { + if (tif->tif_dir.td_extrasamples) + { + uint16 na; + uint16* nb; + TIFFGetFieldDefaulted(tif,TIFFTAG_EXTRASAMPLES,&na,&nb); + if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_EXTRASAMPLES,na,nb)) + goto bad; + } + } + if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) + { + if (!TIFFWriteDirectoryTagShortPerSample(tif,&ndir,dir,TIFFTAG_SAMPLEFORMAT,tif->tif_dir.td_sampleformat)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) + { + if (!TIFFWriteDirectoryTagSampleformatArray(tif,&ndir,dir,TIFFTAG_SMINSAMPLEVALUE,tif->tif_dir.td_samplesperpixel,tif->tif_dir.td_sminsamplevalue)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) + { + if (!TIFFWriteDirectoryTagSampleformatArray(tif,&ndir,dir,TIFFTAG_SMAXSAMPLEVALUE,tif->tif_dir.td_samplesperpixel,tif->tif_dir.td_smaxsamplevalue)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH)) + { + if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_IMAGEDEPTH,tif->tif_dir.td_imagedepth)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_TILEDEPTH)) + { + if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,TIFFTAG_TILEDEPTH,tif->tif_dir.td_tiledepth)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS)) + { + if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_HALFTONEHINTS,2,&tif->tif_dir.td_halftonehints[0])) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING)) + { + if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,TIFFTAG_YCBCRSUBSAMPLING,2,&tif->tif_dir.td_ycbcrsubsampling[0])) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) + { + if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,TIFFTAG_YCBCRPOSITIONING,tif->tif_dir.td_ycbcrpositioning)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) + { + if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,TIFFTAG_REFERENCEBLACKWHITE,6,tif->tif_dir.td_refblackwhite)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) + { + if (!TIFFWriteDirectoryTagTransferfunction(tif,&ndir,dir)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_INKNAMES)) + { + if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,TIFFTAG_INKNAMES,tif->tif_dir.td_inknameslen,tif->tif_dir.td_inknames)) + goto bad; + } + if (TIFFFieldSet(tif,FIELD_SUBIFD)) + { + if (!TIFFWriteDirectoryTagSubifd(tif,&ndir,dir)) + goto bad; + } + { + uint32 n; + for (n=0; ntif_nfields; n++) { + const TIFFField* o; + o = tif->tif_fields[n]; + if ((o->field_bit>=FIELD_CODEC)&&(TIFFFieldSet(tif,o->field_bit))) + { + switch (o->get_field_type) + { + case TIFF_SETGET_ASCII: + { + uint32 pa; + char* pb; + assert(o->field_type==TIFF_ASCII); + assert(o->field_readcount==TIFF_VARIABLE); + assert(o->field_passcount==0); + TIFFGetField(tif,o->field_tag,&pb); + pa=(uint32)(strlen(pb)); + if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,(uint16)o->field_tag,pa,pb)) + goto bad; + } + break; + case TIFF_SETGET_UINT16: + { + uint16 p; + assert(o->field_type==TIFF_SHORT); + assert(o->field_readcount==1); + assert(o->field_passcount==0); + TIFFGetField(tif,o->field_tag,&p); + if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,(uint16)o->field_tag,p)) + goto bad; + } + break; + case TIFF_SETGET_UINT32: + { + uint32 p; + assert(o->field_type==TIFF_LONG); + assert(o->field_readcount==1); + assert(o->field_passcount==0); + TIFFGetField(tif,o->field_tag,&p); + if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,(uint16)o->field_tag,p)) + goto bad; + } + break; + case TIFF_SETGET_C32_UINT8: + { + uint32 pa; + void* pb; + assert(o->field_type==TIFF_UNDEFINED); + assert(o->field_readcount==TIFF_VARIABLE2); + assert(o->field_passcount==1); + TIFFGetField(tif,o->field_tag,&pa,&pb); + if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,(uint16)o->field_tag,pa,pb)) + goto bad; + } + break; + default: + assert(0); /* we should never get here */ + break; + } + } + } + } + } + for (m=0; m<(uint32)(tif->tif_dir.td_customValueCount); m++) + { + uint16 tag = (uint16)tif->tif_dir.td_customValues[m].info->field_tag; + uint32 count = tif->tif_dir.td_customValues[m].count; + switch (tif->tif_dir.td_customValues[m].info->field_type) + { + case TIFF_ASCII: + if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_UNDEFINED: + if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_BYTE: + if (!TIFFWriteDirectoryTagByteArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_SBYTE: + if (!TIFFWriteDirectoryTagSbyteArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_SHORT: + if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_SSHORT: + if (!TIFFWriteDirectoryTagSshortArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_LONG: + if (!TIFFWriteDirectoryTagLongArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_SLONG: + if (!TIFFWriteDirectoryTagSlongArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_LONG8: + if (!TIFFWriteDirectoryTagLong8Array(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_SLONG8: + if (!TIFFWriteDirectoryTagSlong8Array(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_RATIONAL: + if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_SRATIONAL: + if (!TIFFWriteDirectoryTagSrationalArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_FLOAT: + if (!TIFFWriteDirectoryTagFloatArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_DOUBLE: + if (!TIFFWriteDirectoryTagDoubleArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_IFD: + if (!TIFFWriteDirectoryTagIfdArray(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + case TIFF_IFD8: + if (!TIFFWriteDirectoryTagIfdIfd8Array(tif,&ndir,dir,tag,count,tif->tif_dir.td_customValues[m].value)) + goto bad; + break; + default: + assert(0); /* we should never get here */ + break; + } + } + if (dir!=NULL) + break; + dir=_TIFFmalloc(ndir*sizeof(TIFFDirEntry)); + if (dir==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + goto bad; + } + if (isimage) + { + if ((tif->tif_diroff==0)&&(!TIFFLinkDirectory(tif))) + goto bad; + } + else + tif->tif_diroff=(TIFFSeekFile(tif,0,SEEK_END)+1)&(~((toff_t)1)); + if (pdiroff!=NULL) + *pdiroff=tif->tif_diroff; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + dirsize=2+ndir*12+4; + else + dirsize=8+ndir*20+8; + tif->tif_dataoff=tif->tif_diroff+dirsize; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + tif->tif_dataoff=(uint32)tif->tif_dataoff; + if ((tif->tif_dataofftif_diroff)||(tif->tif_dataoff<(uint64)dirsize)) + { + TIFFErrorExt(tif->tif_clientdata,module,"Maximum TIFF file size exceeded"); + goto bad; + } + if (tif->tif_dataoff&1) + tif->tif_dataoff++; + if (isimage) + tif->tif_curdir++; + } + if (isimage) + { + if (TIFFFieldSet(tif,FIELD_SUBIFD)&&(tif->tif_subifdoff==0)) + { + uint32 na; + TIFFDirEntry* nb; + for (na=0, nb=dir; ; na++, nb++) + { + if( na == ndir ) { - uint32 pa; - char* pb; - assert(o->field_type==TIFF_ASCII); - assert(o->field_readcount==TIFF_VARIABLE); - assert(o->field_passcount==0); - TIFFGetField(tif,o->field_tag,&pb); - pa=(uint32)(strlen(pb)); - if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,o->field_tag,pa,pb)) - goto bad; + TIFFErrorExt(tif->tif_clientdata,module, + "Cannot find SubIFD tag"); + goto bad; } - break; - case TIFF_SETGET_UINT16: - { - uint16 p; - assert(o->field_type==TIFF_SHORT); - assert(o->field_readcount==1); - assert(o->field_passcount==0); - TIFFGetField(tif,o->field_tag,&p); - if (!TIFFWriteDirectoryTagShort(tif,&ndir,dir,o->field_tag,p)) - goto bad; - } - break; - case TIFF_SETGET_UINT32: - { - uint32 p; - assert(o->field_type==TIFF_LONG); - assert(o->field_readcount==1); - assert(o->field_passcount==0); - TIFFGetField(tif,o->field_tag,&p); - if (!TIFFWriteDirectoryTagLong(tif,&ndir,dir,o->field_tag,p)) - goto bad; - } - break; - case TIFF_SETGET_C32_UINT8: - { - uint32 pa; - void* pb; - assert(o->field_type==TIFF_UNDEFINED); - assert(o->field_readcount==TIFF_VARIABLE2); - assert(o->field_passcount==1); - TIFFGetField(tif,o->field_tag,&pa,&pb); - if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,o->field_tag,pa,pb)) - goto bad; - } - break; - default: - assert(0); /* we should never get here */ - break; - } - } - } - } - } - for (m=0; m<(uint32)(tif->tif_dir.td_customValueCount); m++) - { - switch (tif->tif_dir.td_customValues[m].info->field_type) - { - case TIFF_ASCII: - if (!TIFFWriteDirectoryTagAscii(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_UNDEFINED: - if (!TIFFWriteDirectoryTagUndefinedArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_BYTE: - if (!TIFFWriteDirectoryTagByteArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_SBYTE: - if (!TIFFWriteDirectoryTagSbyteArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_SHORT: - if (!TIFFWriteDirectoryTagShortArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_SSHORT: - if (!TIFFWriteDirectoryTagSshortArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_LONG: - if (!TIFFWriteDirectoryTagLongArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_SLONG: - if (!TIFFWriteDirectoryTagSlongArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_LONG8: - if (!TIFFWriteDirectoryTagLong8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_SLONG8: - if (!TIFFWriteDirectoryTagSlong8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_RATIONAL: - if (!TIFFWriteDirectoryTagRationalArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_SRATIONAL: - if (!TIFFWriteDirectoryTagSrationalArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_FLOAT: - if (!TIFFWriteDirectoryTagFloatArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_DOUBLE: - if (!TIFFWriteDirectoryTagDoubleArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_IFD: - if (!TIFFWriteDirectoryTagIfdArray(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - case TIFF_IFD8: - if (!TIFFWriteDirectoryTagIfdIfd8Array(tif,&ndir,dir,tif->tif_dir.td_customValues[m].info->field_tag,tif->tif_dir.td_customValues[m].count,tif->tif_dir.td_customValues[m].value)) - goto bad; - break; - default: - assert(0); /* we should never get here */ - break; - } - } - if (dir!=NULL) - break; - dir=_TIFFmalloc(ndir*sizeof(TIFFDirEntry)); - if (dir==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - goto bad; - } - if (isimage) - { - if ((tif->tif_diroff==0)&&(!TIFFLinkDirectory(tif))) - goto bad; - } - else - tif->tif_diroff=(TIFFSeekFile(tif,0,SEEK_END)+1)&(~1); - if (pdiroff!=NULL) - *pdiroff=tif->tif_diroff; - if (!(tif->tif_flags&TIFF_BIGTIFF)) - dirsize=2+ndir*12+4; - else - dirsize=8+ndir*20+8; - tif->tif_dataoff=tif->tif_diroff+dirsize; - if (!(tif->tif_flags&TIFF_BIGTIFF)) - tif->tif_dataoff=(uint32)tif->tif_dataoff; - if ((tif->tif_dataofftif_diroff)||(tif->tif_dataoff<(uint64)dirsize)) - { - TIFFErrorExt(tif->tif_clientdata,module,"Maximum TIFF file size exceeded"); - goto bad; - } - if (tif->tif_dataoff&1) - tif->tif_dataoff++; - if (isimage) - tif->tif_curdir++; - } - if (isimage) - { - if (TIFFFieldSet(tif,FIELD_SUBIFD)&&(tif->tif_subifdoff==0)) - { - uint32 na; - TIFFDirEntry* nb; - for (na=0, nb=dir; ; na++, nb++) - { - assert(natdir_tag==TIFFTAG_SUBIFD) - break; - } - if (!(tif->tif_flags&TIFF_BIGTIFF)) - tif->tif_subifdoff=tif->tif_diroff+2+na*12+8; - else - tif->tif_subifdoff=tif->tif_diroff+8+na*20+12; - } - } - dirmem=_TIFFmalloc(dirsize); - if (dirmem==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - goto bad; - } - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - uint8* n; - uint32 nTmp; - TIFFDirEntry* o; - n=dirmem; - *(uint16*)n=ndir; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)n); - n+=2; - o=dir; - for (m=0; mtdir_tag; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)n); - n+=2; - *(uint16*)n=o->tdir_type; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)n); - n+=2; - nTmp = (uint32)o->tdir_count; - _TIFFmemcpy(n,&nTmp,4); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)n); - n+=4; - /* This is correct. The data has been */ - /* swabbed previously in TIFFWriteDirectoryTagData */ - _TIFFmemcpy(n,&o->tdir_offset,4); - n+=4; - o++; - } - nTmp = (uint32)tif->tif_nextdiroff; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&nTmp); - _TIFFmemcpy(n,&nTmp,4); - } - else - { - uint8* n; - TIFFDirEntry* o; - n=dirmem; - *(uint64*)n=ndir; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)n); - n+=8; - o=dir; - for (m=0; mtdir_tag; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)n); - n+=2; - *(uint16*)n=o->tdir_type; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)n); - n+=2; - _TIFFmemcpy(n,&o->tdir_count,8); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)n); - n+=8; - _TIFFmemcpy(n,&o->tdir_offset,8); - n+=8; - o++; - } - _TIFFmemcpy(n,&tif->tif_nextdiroff,8); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)n); - } - _TIFFfree(dir); - dir=NULL; - if (!SeekOK(tif,tif->tif_diroff)) - { - TIFFErrorExt(tif->tif_clientdata,module,"IO error writing directory"); - goto bad; - } - if (!WriteOK(tif,dirmem,(tmsize_t)dirsize)) - { - TIFFErrorExt(tif->tif_clientdata,module,"IO error writing directory"); - goto bad; - } - _TIFFfree(dirmem); - if (imagedone) - { - TIFFFreeDirectory(tif); - tif->tif_flags &= ~TIFF_DIRTYDIRECT; - tif->tif_flags &= ~TIFF_DIRTYSTRIP; - (*tif->tif_cleanup)(tif); - /* - * Reset directory-related state for subsequent - * directories. - */ - TIFFCreateDirectory(tif); - } - return(1); + if (nb->tdir_tag==TIFFTAG_SUBIFD) + break; + } + if (!(tif->tif_flags&TIFF_BIGTIFF)) + tif->tif_subifdoff=tif->tif_diroff+2+na*12+8; + else + tif->tif_subifdoff=tif->tif_diroff+8+na*20+12; + } + } + dirmem=_TIFFmalloc(dirsize); + if (dirmem==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + goto bad; + } + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + uint8* n; + uint32 nTmp; + TIFFDirEntry* o; + n=dirmem; + *(uint16*)n=(uint16)ndir; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)n); + n+=2; + o=dir; + for (m=0; mtdir_tag; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)n); + n+=2; + *(uint16*)n=o->tdir_type; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)n); + n+=2; + nTmp = (uint32)o->tdir_count; + _TIFFmemcpy(n,&nTmp,4); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)n); + n+=4; + /* This is correct. The data has been */ + /* swabbed previously in TIFFWriteDirectoryTagData */ + _TIFFmemcpy(n,&o->tdir_offset,4); + n+=4; + o++; + } + nTmp = (uint32)tif->tif_nextdiroff; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&nTmp); + _TIFFmemcpy(n,&nTmp,4); + } + else + { + uint8* n; + TIFFDirEntry* o; + n=dirmem; + *(uint64*)n=ndir; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)n); + n+=8; + o=dir; + for (m=0; mtdir_tag; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)n); + n+=2; + *(uint16*)n=o->tdir_type; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)n); + n+=2; + _TIFFmemcpy(n,&o->tdir_count,8); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)n); + n+=8; + _TIFFmemcpy(n,&o->tdir_offset,8); + n+=8; + o++; + } + _TIFFmemcpy(n,&tif->tif_nextdiroff,8); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)n); + } + _TIFFfree(dir); + dir=NULL; + if (!SeekOK(tif,tif->tif_diroff)) + { + TIFFErrorExt(tif->tif_clientdata,module,"IO error writing directory"); + goto bad; + } + if (!WriteOK(tif,dirmem,(tmsize_t)dirsize)) + { + TIFFErrorExt(tif->tif_clientdata,module,"IO error writing directory"); + goto bad; + } + _TIFFfree(dirmem); + if (imagedone) + { + TIFFFreeDirectory(tif); + tif->tif_flags &= ~TIFF_DIRTYDIRECT; + tif->tif_flags &= ~TIFF_DIRTYSTRIP; + (*tif->tif_cleanup)(tif); + /* + * Reset directory-related state for subsequent + * directories. + */ + TIFFCreateDirectory(tif); + } + return(1); bad: - if (dir!=NULL) - _TIFFfree(dir); - if (dirmem!=NULL) - _TIFFfree(dirmem); - return(0); + if (dir!=NULL) + _TIFFfree(dir); + if (dirmem!=NULL) + _TIFFfree(dirmem); + return(0); +} + +static float TIFFClampDoubleToFloat( double val ) +{ + if( val > FLT_MAX ) + return FLT_MAX; + if( val < -FLT_MAX ) + return -FLT_MAX; + return (float)val; +} + +static int8 TIFFClampDoubleToInt8( double val ) +{ + if( val > 127 ) + return 127; + if( val < -128 || val != val ) + return -128; + return (int8)val; +} + +static int16 TIFFClampDoubleToInt16( double val ) +{ + if( val > 32767 ) + return 32767; + if( val < -32768 || val != val ) + return -32768; + return (int16)val; +} + +static int32 TIFFClampDoubleToInt32( double val ) +{ + if( val > 0x7FFFFFFF ) + return 0x7FFFFFFF; + if( val < -0x7FFFFFFF-1 || val != val ) + return -0x7FFFFFFF-1; + return (int32)val; +} + +static uint8 TIFFClampDoubleToUInt8( double val ) +{ + if( val < 0 ) + return 0; + if( val > 255 || val != val ) + return 255; + return (uint8)val; +} + +static uint16 TIFFClampDoubleToUInt16( double val ) +{ + if( val < 0 ) + return 0; + if( val > 65535 || val != val ) + return 65535; + return (uint16)val; +} + +static uint32 TIFFClampDoubleToUInt32( double val ) +{ + if( val < 0 ) + return 0; + if( val > 0xFFFFFFFFU || val != val ) + return 0xFFFFFFFFU; + return (uint32)val; } static int TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value) { - static const char module[] = "TIFFWriteDirectoryTagSampleformatArray"; - void* conv; - uint32 i; - int ok; - conv = _TIFFmalloc(count*sizeof(double)); - if (conv == NULL) - { - TIFFErrorExt(tif->tif_clientdata, module, "Out of memory"); - return (0); - } + static const char module[] = "TIFFWriteDirectoryTagSampleformatArray"; + void* conv; + uint32 i; + int ok; + conv = _TIFFmalloc(count*sizeof(double)); + if (conv == NULL) + { + TIFFErrorExt(tif->tif_clientdata, module, "Out of memory"); + return (0); + } - switch (tif->tif_dir.td_sampleformat) - { - case SAMPLEFORMAT_IEEEFP: - if (tif->tif_dir.td_bitspersample<=32) - { - for (i = 0; i < count; ++i) - ((float*)conv)[i] = (float)value[i]; - ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv); - } - else - { - ok = TIFFWriteDirectoryTagDoubleArray(tif,ndir,dir,tag,count,value); - } - break; - case SAMPLEFORMAT_INT: - if (tif->tif_dir.td_bitspersample<=8) - { - for (i = 0; i < count; ++i) - ((int8*)conv)[i] = (int8)value[i]; - ok = TIFFWriteDirectoryTagSbyteArray(tif,ndir,dir,tag,count,(int8*)conv); - } - else if (tif->tif_dir.td_bitspersample<=16) - { - for (i = 0; i < count; ++i) - ((int16*)conv)[i] = (int16)value[i]; - ok = TIFFWriteDirectoryTagSshortArray(tif,ndir,dir,tag,count,(int16*)conv); - } - else - { - for (i = 0; i < count; ++i) - ((int32*)conv)[i] = (int32)value[i]; - ok = TIFFWriteDirectoryTagSlongArray(tif,ndir,dir,tag,count,(int32*)conv); - } - break; - case SAMPLEFORMAT_UINT: - if (tif->tif_dir.td_bitspersample<=8) - { - for (i = 0; i < count; ++i) - ((uint8*)conv)[i] = (uint8)value[i]; - ok = TIFFWriteDirectoryTagByteArray(tif,ndir,dir,tag,count,(uint8*)conv); - } - else if (tif->tif_dir.td_bitspersample<=16) - { - for (i = 0; i < count; ++i) - ((uint16*)conv)[i] = (uint16)value[i]; - ok = TIFFWriteDirectoryTagShortArray(tif,ndir,dir,tag,count,(uint16*)conv); - } - else - { - for (i = 0; i < count; ++i) - ((uint32*)conv)[i] = (uint32)value[i]; - ok = TIFFWriteDirectoryTagLongArray(tif,ndir,dir,tag,count,(uint32*)conv); - } - break; - default: - ok = 0; - } + switch (tif->tif_dir.td_sampleformat) + { + case SAMPLEFORMAT_IEEEFP: + if (tif->tif_dir.td_bitspersample<=32) + { + for (i = 0; i < count; ++i) + ((float*)conv)[i] = TIFFClampDoubleToFloat(value[i]); + ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv); + } + else + { + ok = TIFFWriteDirectoryTagDoubleArray(tif,ndir,dir,tag,count,value); + } + break; + case SAMPLEFORMAT_INT: + if (tif->tif_dir.td_bitspersample<=8) + { + for (i = 0; i < count; ++i) + ((int8*)conv)[i] = TIFFClampDoubleToInt8(value[i]); + ok = TIFFWriteDirectoryTagSbyteArray(tif,ndir,dir,tag,count,(int8*)conv); + } + else if (tif->tif_dir.td_bitspersample<=16) + { + for (i = 0; i < count; ++i) + ((int16*)conv)[i] = TIFFClampDoubleToInt16(value[i]); + ok = TIFFWriteDirectoryTagSshortArray(tif,ndir,dir,tag,count,(int16*)conv); + } + else + { + for (i = 0; i < count; ++i) + ((int32*)conv)[i] = TIFFClampDoubleToInt32(value[i]); + ok = TIFFWriteDirectoryTagSlongArray(tif,ndir,dir,tag,count,(int32*)conv); + } + break; + case SAMPLEFORMAT_UINT: + if (tif->tif_dir.td_bitspersample<=8) + { + for (i = 0; i < count; ++i) + ((uint8*)conv)[i] = TIFFClampDoubleToUInt8(value[i]); + ok = TIFFWriteDirectoryTagByteArray(tif,ndir,dir,tag,count,(uint8*)conv); + } + else if (tif->tif_dir.td_bitspersample<=16) + { + for (i = 0; i < count; ++i) + ((uint16*)conv)[i] = TIFFClampDoubleToUInt16(value[i]); + ok = TIFFWriteDirectoryTagShortArray(tif,ndir,dir,tag,count,(uint16*)conv); + } + else + { + for (i = 0; i < count; ++i) + ((uint32*)conv)[i] = TIFFClampDoubleToUInt32(value[i]); + ok = TIFFWriteDirectoryTagLongArray(tif,ndir,dir,tag,count,(uint32*)conv); + } + break; + default: + ok = 0; + } - _TIFFfree(conv); - return (ok); + _TIFFfree(conv); + return (ok); } #if 0 static int TIFFWriteDirectoryTagSampleformatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value) { - switch (tif->tif_dir.td_sampleformat) - { - case SAMPLEFORMAT_IEEEFP: - if (tif->tif_dir.td_bitspersample<=32) - return(TIFFWriteDirectoryTagFloatPerSample(tif,ndir,dir,tag,(float)value)); - else - return(TIFFWriteDirectoryTagDoublePerSample(tif,ndir,dir,tag,value)); - case SAMPLEFORMAT_INT: - if (tif->tif_dir.td_bitspersample<=8) - return(TIFFWriteDirectoryTagSbytePerSample(tif,ndir,dir,tag,(int8)value)); - else if (tif->tif_dir.td_bitspersample<=16) - return(TIFFWriteDirectoryTagSshortPerSample(tif,ndir,dir,tag,(int16)value)); - else - return(TIFFWriteDirectoryTagSlongPerSample(tif,ndir,dir,tag,(int32)value)); - case SAMPLEFORMAT_UINT: - if (tif->tif_dir.td_bitspersample<=8) - return(TIFFWriteDirectoryTagBytePerSample(tif,ndir,dir,tag,(uint8)value)); - else if (tif->tif_dir.td_bitspersample<=16) - return(TIFFWriteDirectoryTagShortPerSample(tif,ndir,dir,tag,(uint16)value)); - else - return(TIFFWriteDirectoryTagLongPerSample(tif,ndir,dir,tag,(uint32)value)); - default: - return(1); - } + switch (tif->tif_dir.td_sampleformat) + { + case SAMPLEFORMAT_IEEEFP: + if (tif->tif_dir.td_bitspersample<=32) + return(TIFFWriteDirectoryTagFloatPerSample(tif,ndir,dir,tag,(float)value)); + else + return(TIFFWriteDirectoryTagDoublePerSample(tif,ndir,dir,tag,value)); + case SAMPLEFORMAT_INT: + if (tif->tif_dir.td_bitspersample<=8) + return(TIFFWriteDirectoryTagSbytePerSample(tif,ndir,dir,tag,(int8)value)); + else if (tif->tif_dir.td_bitspersample<=16) + return(TIFFWriteDirectoryTagSshortPerSample(tif,ndir,dir,tag,(int16)value)); + else + return(TIFFWriteDirectoryTagSlongPerSample(tif,ndir,dir,tag,(int32)value)); + case SAMPLEFORMAT_UINT: + if (tif->tif_dir.td_bitspersample<=8) + return(TIFFWriteDirectoryTagBytePerSample(tif,ndir,dir,tag,(uint8)value)); + else if (tif->tif_dir.td_bitspersample<=16) + return(TIFFWriteDirectoryTagShortPerSample(tif,ndir,dir,tag,(uint16)value)); + else + return(TIFFWriteDirectoryTagLongPerSample(tif,ndir,dir,tag,(uint32)value)); + default: + return(1); + } } #endif static int TIFFWriteDirectoryTagAscii(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, char* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedAscii(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedAscii(tif,ndir,dir,tag,count,value)); } static int TIFFWriteDirectoryTagUndefinedArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedUndefinedArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedUndefinedArray(tif,ndir,dir,tag,count,value)); } #ifdef notdef static int TIFFWriteDirectoryTagByte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedByte(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedByte(tif,ndir,dir,tag,value)); } #endif static int TIFFWriteDirectoryTagByteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedByteArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedByteArray(tif,ndir,dir,tag,count,value)); } #if 0 static int TIFFWriteDirectoryTagBytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value) { - static const char module[] = "TIFFWriteDirectoryTagBytePerSample"; - uint8* m; - uint8* na; - uint16 nb; - int o; - if (dir==NULL) - { - (*ndir)++; - return(1); - } - m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(uint8)); - if (m==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) - *na=value; - o=TIFFWriteDirectoryTagCheckedByteArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); - _TIFFfree(m); - return(o); + static const char module[] = "TIFFWriteDirectoryTagBytePerSample"; + uint8* m; + uint8* na; + uint16 nb; + int o; + if (dir==NULL) + { + (*ndir)++; + return(1); + } + m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(uint8)); + if (m==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) + *na=value; + o=TIFFWriteDirectoryTagCheckedByteArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); + _TIFFfree(m); + return(o); } #endif @@ -1110,201 +1193,201 @@ TIFFWriteDirectoryTagBytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, u static int TIFFWriteDirectoryTagSbyte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedSbyte(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedSbyte(tif,ndir,dir,tag,value)); } #endif static int TIFFWriteDirectoryTagSbyteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int8* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedSbyteArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedSbyteArray(tif,ndir,dir,tag,count,value)); } #if 0 static int TIFFWriteDirectoryTagSbytePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value) { - static const char module[] = "TIFFWriteDirectoryTagSbytePerSample"; - int8* m; - int8* na; - uint16 nb; - int o; - if (dir==NULL) - { - (*ndir)++; - return(1); - } - m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(int8)); - if (m==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) - *na=value; - o=TIFFWriteDirectoryTagCheckedSbyteArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); - _TIFFfree(m); - return(o); + static const char module[] = "TIFFWriteDirectoryTagSbytePerSample"; + int8* m; + int8* na; + uint16 nb; + int o; + if (dir==NULL) + { + (*ndir)++; + return(1); + } + m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(int8)); + if (m==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) + *na=value; + o=TIFFWriteDirectoryTagCheckedSbyteArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); + _TIFFfree(m); + return(o); } #endif static int TIFFWriteDirectoryTagShort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedShort(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedShort(tif,ndir,dir,tag,value)); } static int TIFFWriteDirectoryTagShortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint16* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,tag,count,value)); } static int TIFFWriteDirectoryTagShortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value) { - static const char module[] = "TIFFWriteDirectoryTagShortPerSample"; - uint16* m; - uint16* na; - uint16 nb; - int o; - if (dir==NULL) - { - (*ndir)++; - return(1); - } - m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(uint16)); - if (m==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) - *na=value; - o=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); - _TIFFfree(m); - return(o); + static const char module[] = "TIFFWriteDirectoryTagShortPerSample"; + uint16* m; + uint16* na; + uint16 nb; + int o; + if (dir==NULL) + { + (*ndir)++; + return(1); + } + m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(uint16)); + if (m==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) + *na=value; + o=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); + _TIFFfree(m); + return(o); } #ifdef notdef static int TIFFWriteDirectoryTagSshort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedSshort(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedSshort(tif,ndir,dir,tag,value)); } #endif static int TIFFWriteDirectoryTagSshortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int16* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedSshortArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedSshortArray(tif,ndir,dir,tag,count,value)); } #if 0 static int TIFFWriteDirectoryTagSshortPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value) { - static const char module[] = "TIFFWriteDirectoryTagSshortPerSample"; - int16* m; - int16* na; - uint16 nb; - int o; - if (dir==NULL) - { - (*ndir)++; - return(1); - } - m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(int16)); - if (m==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) - *na=value; - o=TIFFWriteDirectoryTagCheckedSshortArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); - _TIFFfree(m); - return(o); + static const char module[] = "TIFFWriteDirectoryTagSshortPerSample"; + int16* m; + int16* na; + uint16 nb; + int o; + if (dir==NULL) + { + (*ndir)++; + return(1); + } + m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(int16)); + if (m==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) + *na=value; + o=TIFFWriteDirectoryTagCheckedSshortArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); + _TIFFfree(m); + return(o); } #endif static int TIFFWriteDirectoryTagLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value)); } static int TIFFWriteDirectoryTagLongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,value)); } #if 0 static int TIFFWriteDirectoryTagLongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value) { - static const char module[] = "TIFFWriteDirectoryTagLongPerSample"; - uint32* m; - uint32* na; - uint16 nb; - int o; - if (dir==NULL) - { - (*ndir)++; - return(1); - } - m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(uint32)); - if (m==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) - *na=value; - o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); - _TIFFfree(m); - return(o); + static const char module[] = "TIFFWriteDirectoryTagLongPerSample"; + uint32* m; + uint32* na; + uint16 nb; + int o; + if (dir==NULL) + { + (*ndir)++; + return(1); + } + m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(uint32)); + if (m==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) + *na=value; + o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); + _TIFFfree(m); + return(o); } #endif @@ -1312,51 +1395,51 @@ TIFFWriteDirectoryTagLongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, u static int TIFFWriteDirectoryTagSlong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedSlong(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedSlong(tif,ndir,dir,tag,value)); } #endif static int TIFFWriteDirectoryTagSlongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int32* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedSlongArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedSlongArray(tif,ndir,dir,tag,count,value)); } #if 0 static int TIFFWriteDirectoryTagSlongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value) { - static const char module[] = "TIFFWriteDirectoryTagSlongPerSample"; - int32* m; - int32* na; - uint16 nb; - int o; - if (dir==NULL) - { - (*ndir)++; - return(1); - } - m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(int32)); - if (m==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) - *na=value; - o=TIFFWriteDirectoryTagCheckedSlongArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); - _TIFFfree(m); - return(o); + static const char module[] = "TIFFWriteDirectoryTagSlongPerSample"; + int32* m; + int32* na; + uint16 nb; + int o; + if (dir==NULL) + { + (*ndir)++; + return(1); + } + m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(int32)); + if (m==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) + *na=value; + o=TIFFWriteDirectoryTagCheckedSlongArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); + _TIFFfree(m); + return(o); } #endif @@ -1364,217 +1447,217 @@ TIFFWriteDirectoryTagSlongPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, static int TIFFWriteDirectoryTagLong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint64 value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedLong8(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedLong8(tif,ndir,dir,tag,value)); } #endif static int TIFFWriteDirectoryTagLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir,tag,count,value)); } #ifdef notdef static int TIFFWriteDirectoryTagSlong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int64 value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedSlong8(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedSlong8(tif,ndir,dir,tag,value)); } #endif static int TIFFWriteDirectoryTagSlong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int64* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedSlong8Array(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedSlong8Array(tif,ndir,dir,tag,count,value)); } static int TIFFWriteDirectoryTagRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedRational(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedRational(tif,ndir,dir,tag,value)); } static int TIFFWriteDirectoryTagRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedRationalArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedRationalArray(tif,ndir,dir,tag,count,value)); } static int TIFFWriteDirectoryTagSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedSrationalArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedSrationalArray(tif,ndir,dir,tag,count,value)); } #ifdef notdef static int TIFFWriteDirectoryTagFloat(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedFloat(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedFloat(tif,ndir,dir,tag,value)); } #endif static int TIFFWriteDirectoryTagFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedFloatArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedFloatArray(tif,ndir,dir,tag,count,value)); } #if 0 static int TIFFWriteDirectoryTagFloatPerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value) { - static const char module[] = "TIFFWriteDirectoryTagFloatPerSample"; - float* m; - float* na; - uint16 nb; - int o; - if (dir==NULL) - { - (*ndir)++; - return(1); - } - m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(float)); - if (m==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) - *na=value; - o=TIFFWriteDirectoryTagCheckedFloatArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); - _TIFFfree(m); - return(o); + static const char module[] = "TIFFWriteDirectoryTagFloatPerSample"; + float* m; + float* na; + uint16 nb; + int o; + if (dir==NULL) + { + (*ndir)++; + return(1); + } + m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(float)); + if (m==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) + *na=value; + o=TIFFWriteDirectoryTagCheckedFloatArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); + _TIFFfree(m); + return(o); } #endif #ifdef notdef static int TIFFWriteDirectoryTagDouble(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedDouble(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedDouble(tif,ndir,dir,tag,value)); } #endif static int TIFFWriteDirectoryTagDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedDoubleArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedDoubleArray(tif,ndir,dir,tag,count,value)); } #if 0 static int TIFFWriteDirectoryTagDoublePerSample(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value) { - static const char module[] = "TIFFWriteDirectoryTagDoublePerSample"; - double* m; - double* na; - uint16 nb; - int o; - if (dir==NULL) - { - (*ndir)++; - return(1); - } - m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(double)); - if (m==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) - *na=value; - o=TIFFWriteDirectoryTagCheckedDoubleArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); - _TIFFfree(m); - return(o); + static const char module[] = "TIFFWriteDirectoryTagDoublePerSample"; + double* m; + double* na; + uint16 nb; + int o; + if (dir==NULL) + { + (*ndir)++; + return(1); + } + m=_TIFFmalloc(tif->tif_dir.td_samplesperpixel*sizeof(double)); + if (m==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + for (na=m, nb=0; nbtif_dir.td_samplesperpixel; na++, nb++) + *na=value; + o=TIFFWriteDirectoryTagCheckedDoubleArray(tif,ndir,dir,tag,tif->tif_dir.td_samplesperpixel,m); + _TIFFfree(m); + return(o); } #endif static int TIFFWriteDirectoryTagIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedIfdArray(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedIfdArray(tif,ndir,dir,tag,count,value)); } #ifdef notdef static int TIFFWriteDirectoryTagIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - return(TIFFWriteDirectoryTagCheckedIfd8Array(tif,ndir,dir,tag,count,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + return(TIFFWriteDirectoryTagCheckedIfd8Array(tif,ndir,dir,tag,count,value)); } #endif static int TIFFWriteDirectoryTagShortLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value) { - if (dir==NULL) - { - (*ndir)++; - return(1); - } - if (value<=0xFFFF) - return(TIFFWriteDirectoryTagCheckedShort(tif,ndir,dir,tag,(uint16)value)); - else - return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value)); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + if (value<=0xFFFF) + return(TIFFWriteDirectoryTagCheckedShort(tif,ndir,dir,tag,(uint16)value)); + else + return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value)); } /************************************************************************/ @@ -1698,666 +1781,696 @@ TIFFWriteDirectoryTagIfdIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, ui static int TIFFWriteDirectoryTagShortLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) { - static const char module[] = "TIFFWriteDirectoryTagShortLongLong8Array"; - uint64* ma; - uint32 mb; - uint8 n; - int o; - if (dir==NULL) - { - (*ndir)++; - return(1); - } - n=0; - for (ma=value, mb=0; mb0xFFFF)) - n=1; - if ((n==1)&&(*ma>0xFFFFFFFF)) - { - n=2; - break; - } - } - if (n==0) - { - uint16* p; - uint16* q; - p=_TIFFmalloc(count*sizeof(uint16)); - if (p==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - for (ma=value, mb=0, q=p; mbtif_clientdata,module,"Out of memory"); - return(0); - } - for (ma=value, mb=0, q=p; mb0xFFFF)) + n=1; + if ((n==1)&&(*ma>0xFFFFFFFF)) + { + n=2; + break; + } + } + if (n==0) + { + uint16* p; + uint16* q; + p=_TIFFmalloc(count*sizeof(uint16)); + if (p==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + for (ma=value, mb=0, q=p; mbtif_clientdata,module,"Out of memory"); + return(0); + } + for (ma=value, mb=0, q=p; mbtif_dir.td_bitspersample); - n=_TIFFmalloc(3*m*sizeof(uint16)); - if (n==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - _TIFFmemcpy(&n[0],tif->tif_dir.td_colormap[0],m*sizeof(uint16)); - _TIFFmemcpy(&n[m],tif->tif_dir.td_colormap[1],m*sizeof(uint16)); - _TIFFmemcpy(&n[2*m],tif->tif_dir.td_colormap[2],m*sizeof(uint16)); - o=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,TIFFTAG_COLORMAP,3*m,n); - _TIFFfree(n); - return(o); + static const char module[] = "TIFFWriteDirectoryTagColormap"; + uint32 m; + uint16* n; + int o; + if (dir==NULL) + { + (*ndir)++; + return(1); + } + m=(1<tif_dir.td_bitspersample); + n=_TIFFmalloc(3*m*sizeof(uint16)); + if (n==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + _TIFFmemcpy(&n[0],tif->tif_dir.td_colormap[0],m*sizeof(uint16)); + _TIFFmemcpy(&n[m],tif->tif_dir.td_colormap[1],m*sizeof(uint16)); + _TIFFmemcpy(&n[2*m],tif->tif_dir.td_colormap[2],m*sizeof(uint16)); + o=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,TIFFTAG_COLORMAP,3*m,n); + _TIFFfree(n); + return(o); } static int TIFFWriteDirectoryTagTransferfunction(TIFF* tif, uint32* ndir, TIFFDirEntry* dir) { - static const char module[] = "TIFFWriteDirectoryTagTransferfunction"; - uint32 m; - uint16 n; - uint16* o; - int p; - if (dir==NULL) - { - (*ndir)++; - return(1); - } - m=(1<tif_dir.td_bitspersample); - n=tif->tif_dir.td_samplesperpixel-tif->tif_dir.td_extrasamples; - /* - * Check if the table can be written as a single column, - * or if it must be written as 3 columns. Note that we - * write a 3-column tag if there are 2 samples/pixel and - * a single column of data won't suffice--hmm. - */ - if (n>3) - n=3; - if (n==3) - { - if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16))) - n=2; - } - if (n==2) - { - if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16))) - n=1; - } - if (n==0) - n=1; - o=_TIFFmalloc(n*m*sizeof(uint16)); - if (o==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - _TIFFmemcpy(&o[0],tif->tif_dir.td_transferfunction[0],m*sizeof(uint16)); - if (n>1) - _TIFFmemcpy(&o[m],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16)); - if (n>2) - _TIFFmemcpy(&o[2*m],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16)); - p=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,TIFFTAG_TRANSFERFUNCTION,n*m,o); - _TIFFfree(o); - return(p); + static const char module[] = "TIFFWriteDirectoryTagTransferfunction"; + uint32 m; + uint16 n; + uint16* o; + int p; + if (dir==NULL) + { + (*ndir)++; + return(1); + } + m=(1<tif_dir.td_bitspersample); + n=tif->tif_dir.td_samplesperpixel-tif->tif_dir.td_extrasamples; + /* + * Check if the table can be written as a single column, + * or if it must be written as 3 columns. Note that we + * write a 3-column tag if there are 2 samples/pixel and + * a single column of data won't suffice--hmm. + */ + if (n>3) + n=3; + if (n==3) + { + if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16))) + n=2; + } + if (n==2) + { + if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16))) + n=1; + } + if (n==0) + n=1; + o=_TIFFmalloc(n*m*sizeof(uint16)); + if (o==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + _TIFFmemcpy(&o[0],tif->tif_dir.td_transferfunction[0],m*sizeof(uint16)); + if (n>1) + _TIFFmemcpy(&o[m],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16)); + if (n>2) + _TIFFmemcpy(&o[2*m],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16)); + p=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,TIFFTAG_TRANSFERFUNCTION,n*m,o); + _TIFFfree(o); + return(p); } static int TIFFWriteDirectoryTagSubifd(TIFF* tif, uint32* ndir, TIFFDirEntry* dir) { - static const char module[] = "TIFFWriteDirectoryTagSubifd"; - uint64 m; - int n; - if (tif->tif_dir.td_nsubifd==0) - return(1); - if (dir==NULL) - { - (*ndir)++; - return(1); - } - m=tif->tif_dataoff; - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - uint32* o; - uint64* pa; - uint32* pb; - uint16 p; - o=_TIFFmalloc(tif->tif_dir.td_nsubifd*sizeof(uint32)); - if (o==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - pa=tif->tif_dir.td_subifd; - pb=o; - for (p=0; p < tif->tif_dir.td_nsubifd; p++) - { + static const char module[] = "TIFFWriteDirectoryTagSubifd"; + uint64 m; + int n; + if (tif->tif_dir.td_nsubifd==0) + return(1); + if (dir==NULL) + { + (*ndir)++; + return(1); + } + m=tif->tif_dataoff; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + uint32* o; + uint64* pa; + uint32* pb; + uint16 p; + o=_TIFFmalloc(tif->tif_dir.td_nsubifd*sizeof(uint32)); + if (o==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + pa=tif->tif_dir.td_subifd; + pb=o; + for (p=0; p < tif->tif_dir.td_nsubifd; p++) + { assert(pa != 0); - assert(*pa <= 0xFFFFFFFFUL); - *pb++=(uint32)(*pa++); - } - n=TIFFWriteDirectoryTagCheckedIfdArray(tif,ndir,dir,TIFFTAG_SUBIFD,tif->tif_dir.td_nsubifd,o); - _TIFFfree(o); - } - else - n=TIFFWriteDirectoryTagCheckedIfd8Array(tif,ndir,dir,TIFFTAG_SUBIFD,tif->tif_dir.td_nsubifd,tif->tif_dir.td_subifd); - if (!n) - return(0); - /* - * Total hack: if this directory includes a SubIFD - * tag then force the next directories to be - * written as ``sub directories'' of this one. This - * is used to write things like thumbnails and - * image masks that one wants to keep out of the - * normal directory linkage access mechanism. - */ - tif->tif_flags|=TIFF_INSUBIFD; - tif->tif_nsubifd=tif->tif_dir.td_nsubifd; - if (tif->tif_dir.td_nsubifd==1) - tif->tif_subifdoff=0; - else - tif->tif_subifdoff=m; - return(1); + + /* Could happen if an classicTIFF has a SubIFD of type LONG8 (which is illegal) */ + if( *pa > 0xFFFFFFFFUL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Illegal value for SubIFD tag"); + _TIFFfree(o); + return(0); + } + *pb++=(uint32)(*pa++); + } + n=TIFFWriteDirectoryTagCheckedIfdArray(tif,ndir,dir,TIFFTAG_SUBIFD,tif->tif_dir.td_nsubifd,o); + _TIFFfree(o); + } + else + n=TIFFWriteDirectoryTagCheckedIfd8Array(tif,ndir,dir,TIFFTAG_SUBIFD,tif->tif_dir.td_nsubifd,tif->tif_dir.td_subifd); + if (!n) + return(0); + /* + * Total hack: if this directory includes a SubIFD + * tag then force the next directories to be + * written as ``sub directories'' of this one. This + * is used to write things like thumbnails and + * image masks that one wants to keep out of the + * normal directory linkage access mechanism. + */ + tif->tif_flags|=TIFF_INSUBIFD; + tif->tif_nsubifd=tif->tif_dir.td_nsubifd; + if (tif->tif_dir.td_nsubifd==1) + tif->tif_subifdoff=0; + else + tif->tif_subifdoff=m; + return(1); } static int TIFFWriteDirectoryTagCheckedAscii(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, char* value) { - assert(sizeof(char)==1); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_ASCII,count,count,value)); + assert(sizeof(char)==1); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_ASCII,count,count,value)); } static int TIFFWriteDirectoryTagCheckedUndefinedArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value) { - assert(sizeof(uint8)==1); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_UNDEFINED,count,count,value)); + assert(sizeof(uint8)==1); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_UNDEFINED,count,count,value)); } #ifdef notdef static int TIFFWriteDirectoryTagCheckedByte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint8 value) { - assert(sizeof(uint8)==1); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_BYTE,1,1,&value)); + assert(sizeof(uint8)==1); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_BYTE,1,1,&value)); } #endif static int TIFFWriteDirectoryTagCheckedByteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint8* value) { - assert(sizeof(uint8)==1); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_BYTE,count,count,value)); + assert(sizeof(uint8)==1); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_BYTE,count,count,value)); } #ifdef notdef static int TIFFWriteDirectoryTagCheckedSbyte(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int8 value) { - assert(sizeof(int8)==1); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SBYTE,1,1,&value)); + assert(sizeof(int8)==1); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SBYTE,1,1,&value)); } #endif static int TIFFWriteDirectoryTagCheckedSbyteArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int8* value) { - assert(sizeof(int8)==1); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SBYTE,count,count,value)); + assert(sizeof(int8)==1); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SBYTE,count,count,value)); } static int TIFFWriteDirectoryTagCheckedShort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 value) { - uint16 m; - assert(sizeof(uint16)==2); - m=value; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabShort(&m); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SHORT,1,2,&m)); + uint16 m; + assert(sizeof(uint16)==2); + m=value; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabShort(&m); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SHORT,1,2,&m)); } static int TIFFWriteDirectoryTagCheckedShortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint16* value) { - assert(count<0x80000000); - assert(sizeof(uint16)==2); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfShort(value,count); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SHORT,count,count*2,value)); + assert(count<0x80000000); + assert(sizeof(uint16)==2); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfShort(value,count); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SHORT,count,count*2,value)); } #ifdef notdef static int TIFFWriteDirectoryTagCheckedSshort(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int16 value) { - int16 m; - assert(sizeof(int16)==2); - m=value; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabShort((uint16*)(&m)); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SSHORT,1,2,&m)); + int16 m; + assert(sizeof(int16)==2); + m=value; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabShort((uint16*)(&m)); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SSHORT,1,2,&m)); } #endif static int TIFFWriteDirectoryTagCheckedSshortArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int16* value) { - assert(count<0x80000000); - assert(sizeof(int16)==2); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfShort((uint16*)value,count); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SSHORT,count,count*2,value)); + assert(count<0x80000000); + assert(sizeof(int16)==2); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfShort((uint16*)value,count); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SSHORT,count,count*2,value)); } static int TIFFWriteDirectoryTagCheckedLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 value) { - uint32 m; - assert(sizeof(uint32)==4); - m=value; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&m); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG,1,4,&m)); + uint32 m; + assert(sizeof(uint32)==4); + m=value; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&m); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG,1,4,&m)); } static int TIFFWriteDirectoryTagCheckedLongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value) { - assert(count<0x40000000); - assert(sizeof(uint32)==4); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong(value,count); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG,count,count*4,value)); + assert(count<0x40000000); + assert(sizeof(uint32)==4); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong(value,count); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG,count,count*4,value)); } #ifdef notdef static int TIFFWriteDirectoryTagCheckedSlong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int32 value) { - int32 m; - assert(sizeof(int32)==4); - m=value; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong((uint32*)(&m)); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG,1,4,&m)); + int32 m; + assert(sizeof(int32)==4); + m=value; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong((uint32*)(&m)); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG,1,4,&m)); } #endif static int TIFFWriteDirectoryTagCheckedSlongArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int32* value) { - assert(count<0x40000000); - assert(sizeof(int32)==4); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong((uint32*)value,count); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG,count,count*4,value)); + assert(count<0x40000000); + assert(sizeof(int32)==4); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong((uint32*)value,count); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG,count,count*4,value)); } #ifdef notdef static int TIFFWriteDirectoryTagCheckedLong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint64 value) { - uint64 m; - assert(sizeof(uint64)==8); - assert(tif->tif_flags&TIFF_BIGTIFF); - m=value; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8(&m); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG8,1,8,&m)); + uint64 m; + assert(sizeof(uint64)==8); + if( !(tif->tif_flags&TIFF_BIGTIFF) ) { + TIFFErrorExt(tif->tif_clientdata,"TIFFWriteDirectoryTagCheckedLong8","LONG8 not allowed for ClassicTIFF"); + return(0); + } + m=value; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8(&m); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG8,1,8,&m)); } #endif static int TIFFWriteDirectoryTagCheckedLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) { - assert(count<0x20000000); - assert(sizeof(uint64)==8); - assert(tif->tif_flags&TIFF_BIGTIFF); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong8(value,count); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG8,count,count*8,value)); + assert(count<0x20000000); + assert(sizeof(uint64)==8); + if( !(tif->tif_flags&TIFF_BIGTIFF) ) { + TIFFErrorExt(tif->tif_clientdata,"TIFFWriteDirectoryTagCheckedLong8Array","LONG8 not allowed for ClassicTIFF"); + return(0); + } + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong8(value,count); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_LONG8,count,count*8,value)); } #ifdef notdef static int TIFFWriteDirectoryTagCheckedSlong8(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, int64 value) { - int64 m; - assert(sizeof(int64)==8); - assert(tif->tif_flags&TIFF_BIGTIFF); - m=value; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8((uint64*)(&m)); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG8,1,8,&m)); + int64 m; + assert(sizeof(int64)==8); + if( !(tif->tif_flags&TIFF_BIGTIFF) ) { + TIFFErrorExt(tif->tif_clientdata,"TIFFWriteDirectoryTagCheckedSlong8","SLONG8 not allowed for ClassicTIFF"); + return(0); + } + m=value; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8((uint64*)(&m)); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG8,1,8,&m)); } #endif static int TIFFWriteDirectoryTagCheckedSlong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, int64* value) { - assert(count<0x20000000); - assert(sizeof(int64)==8); - assert(tif->tif_flags&TIFF_BIGTIFF); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong8((uint64*)value,count); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG8,count,count*8,value)); + assert(count<0x20000000); + assert(sizeof(int64)==8); + if( !(tif->tif_flags&TIFF_BIGTIFF) ) { + TIFFErrorExt(tif->tif_clientdata,"TIFFWriteDirectoryTagCheckedSlong8Array","SLONG8 not allowed for ClassicTIFF"); + return(0); + } + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong8((uint64*)value,count); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SLONG8,count,count*8,value)); } static int TIFFWriteDirectoryTagCheckedRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value) { - uint32 m[2]; - assert(value>=0.0); - assert(sizeof(uint32)==4); - if (value<=0.0) - { - m[0]=0; - m[1]=1; - } - else if (value==(double)(uint32)value) - { - m[0]=(uint32)value; - m[1]=1; - } - else if (value<1.0) - { - m[0]=(uint32)(value*0xFFFFFFFF); - m[1]=0xFFFFFFFF; - } - else - { - m[0]=0xFFFFFFFF; - m[1]=(uint32)(0xFFFFFFFF/value); - } - if (tif->tif_flags&TIFF_SWAB) - { - TIFFSwabLong(&m[0]); - TIFFSwabLong(&m[1]); - } - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_RATIONAL,1,8,&m[0])); + static const char module[] = "TIFFWriteDirectoryTagCheckedRational"; + uint32 m[2]; + assert(sizeof(uint32)==4); + if( value < 0 ) + { + TIFFErrorExt(tif->tif_clientdata,module,"Negative value is illegal"); + return 0; + } + else if( value != value ) + { + TIFFErrorExt(tif->tif_clientdata,module,"Not-a-number value is illegal"); + return 0; + } + else if (value==0.0) + { + m[0]=0; + m[1]=1; + } + else if (value <= 0xFFFFFFFFU && value==(double)(uint32)value) + { + m[0]=(uint32)value; + m[1]=1; + } + else if (value<1.0) + { + m[0]=(uint32)(value*0xFFFFFFFF); + m[1]=0xFFFFFFFF; + } + else + { + m[0]=0xFFFFFFFF; + m[1]=(uint32)(0xFFFFFFFF/value); + } + if (tif->tif_flags&TIFF_SWAB) + { + TIFFSwabLong(&m[0]); + TIFFSwabLong(&m[1]); + } + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_RATIONAL,1,8,&m[0])); } static int TIFFWriteDirectoryTagCheckedRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value) { - static const char module[] = "TIFFWriteDirectoryTagCheckedRationalArray"; - uint32* m; - float* na; - uint32* nb; - uint32 nc; - int o; - assert(sizeof(uint32)==4); - m=_TIFFmalloc(count*2*sizeof(uint32)); - if (m==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - for (na=value, nb=m, nc=0; nctif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong(m,count*2); - o=TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_RATIONAL,count,count*8,&m[0]); - _TIFFfree(m); - return(o); + static const char module[] = "TIFFWriteDirectoryTagCheckedRationalArray"; + uint32* m; + float* na; + uint32* nb; + uint32 nc; + int o; + assert(sizeof(uint32)==4); + m=_TIFFmalloc(count*2*sizeof(uint32)); + if (m==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + for (na=value, nb=m, nc=0; nc= 0 && *na <= (float)0xFFFFFFFFU && + *na==(float)(uint32)(*na)) + { + nb[0]=(uint32)(*na); + nb[1]=1; + } + else if (*na<1.0) + { + nb[0]=(uint32)((double)(*na)*0xFFFFFFFF); + nb[1]=0xFFFFFFFF; + } + else + { + nb[0]=0xFFFFFFFF; + nb[1]=(uint32)((double)0xFFFFFFFF/(*na)); + } + } + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong(m,count*2); + o=TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_RATIONAL,count,count*8,&m[0]); + _TIFFfree(m); + return(o); } static int TIFFWriteDirectoryTagCheckedSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value) { - static const char module[] = "TIFFWriteDirectoryTagCheckedSrationalArray"; - int32* m; - float* na; - int32* nb; - uint32 nc; - int o; - assert(sizeof(int32)==4); - m=_TIFFmalloc(count*2*sizeof(int32)); - if (m==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - for (na=value, nb=m, nc=0; nc-1.0) - { - nb[0]=-(int32)((-*na)*0x7FFFFFFF); - nb[1]=0x7FFFFFFF; - } - else - { - nb[0]=-0x7FFFFFFF; - nb[1]=(int32)(0x7FFFFFFF/(-*na)); - } - } - else - { - if (*na==(int32)(*na)) - { - nb[0]=(int32)(*na); - nb[1]=1; - } - else if (*na<1.0) - { - nb[0]=(int32)((*na)*0x7FFFFFFF); - nb[1]=0x7FFFFFFF; - } - else - { - nb[0]=0x7FFFFFFF; - nb[1]=(int32)(0x7FFFFFFF/(*na)); - } - } - } - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong((uint32*)m,count*2); - o=TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SRATIONAL,count,count*8,&m[0]); - _TIFFfree(m); - return(o); + static const char module[] = "TIFFWriteDirectoryTagCheckedSrationalArray"; + int32* m; + float* na; + int32* nb; + uint32 nc; + int o; + assert(sizeof(int32)==4); + m=_TIFFmalloc(count*2*sizeof(int32)); + if (m==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + for (na=value, nb=m, nc=0; nc-1.0) + { + nb[0]=-(int32)((double)(-*na)*0x7FFFFFFF); + nb[1]=0x7FFFFFFF; + } + else + { + nb[0]=-0x7FFFFFFF; + nb[1]=(int32)((double)0x7FFFFFFF/(-*na)); + } + } + else + { + if (*na==(int32)(*na)) + { + nb[0]=(int32)(*na); + nb[1]=1; + } + else if (*na<1.0) + { + nb[0]=(int32)((double)(*na)*0x7FFFFFFF); + nb[1]=0x7FFFFFFF; + } + else + { + nb[0]=0x7FFFFFFF; + nb[1]=(int32)((double)0x7FFFFFFF/(*na)); + } + } + } + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong((uint32*)m,count*2); + o=TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_SRATIONAL,count,count*8,&m[0]); + _TIFFfree(m); + return(o); } #ifdef notdef static int TIFFWriteDirectoryTagCheckedFloat(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, float value) { - float m; - assert(sizeof(float)==4); - m=value; - TIFFCvtNativeToIEEEFloat(tif,1,&m); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabFloat(&m); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_FLOAT,1,4,&m)); + float m; + assert(sizeof(float)==4); + m=value; + TIFFCvtNativeToIEEEFloat(tif,1,&m); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabFloat(&m); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_FLOAT,1,4,&m)); } #endif static int TIFFWriteDirectoryTagCheckedFloatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value) { - assert(count<0x40000000); - assert(sizeof(float)==4); - TIFFCvtNativeToIEEEFloat(tif,count,&value); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfFloat(value,count); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_FLOAT,count,count*4,value)); + assert(count<0x40000000); + assert(sizeof(float)==4); + TIFFCvtNativeToIEEEFloat(tif,count,&value); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfFloat(value,count); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_FLOAT,count,count*4,value)); } #ifdef notdef static int TIFFWriteDirectoryTagCheckedDouble(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value) { - double m; - assert(sizeof(double)==8); - m=value; - TIFFCvtNativeToIEEEDouble(tif,1,&m); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabDouble(&m); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_DOUBLE,1,8,&m)); + double m; + assert(sizeof(double)==8); + m=value; + TIFFCvtNativeToIEEEDouble(tif,1,&m); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabDouble(&m); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_DOUBLE,1,8,&m)); } #endif static int TIFFWriteDirectoryTagCheckedDoubleArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value) { - assert(count<0x20000000); - assert(sizeof(double)==8); - TIFFCvtNativeToIEEEDouble(tif,count,&value); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfDouble(value,count); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_DOUBLE,count,count*8,value)); + assert(count<0x20000000); + assert(sizeof(double)==8); + TIFFCvtNativeToIEEEDouble(tif,count,&value); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfDouble(value,count); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_DOUBLE,count,count*8,value)); } static int TIFFWriteDirectoryTagCheckedIfdArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint32* value) { - assert(count<0x40000000); - assert(sizeof(uint32)==4); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong(value,count); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_IFD,count,count*4,value)); + assert(count<0x40000000); + assert(sizeof(uint32)==4); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong(value,count); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_IFD,count,count*4,value)); } static int TIFFWriteDirectoryTagCheckedIfd8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) { - assert(count<0x20000000); - assert(sizeof(uint64)==8); - assert(tif->tif_flags&TIFF_BIGTIFF); - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabArrayOfLong8(value,count); - return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_IFD8,count,count*8,value)); + assert(count<0x20000000); + assert(sizeof(uint64)==8); + assert(tif->tif_flags&TIFF_BIGTIFF); + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabArrayOfLong8(value,count); + return(TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_IFD8,count,count*8,value)); } static int TIFFWriteDirectoryTagData(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint16 datatype, uint32 count, uint32 datalength, void* data) { - static const char module[] = "TIFFWriteDirectoryTagData"; - uint32 m; - m=0; - while (m<(*ndir)) - { - assert(dir[m].tdir_tag!=tag); - if (dir[m].tdir_tag>tag) - break; - m++; - } - if (m<(*ndir)) - { - uint32 n; - for (n=*ndir; n>m; n--) - dir[n]=dir[n-1]; - } - dir[m].tdir_tag=tag; - dir[m].tdir_type=datatype; - dir[m].tdir_count=count; - dir[m].tdir_offset.toff_long8 = 0; - if (datalength<=((tif->tif_flags&TIFF_BIGTIFF)?0x8U:0x4U)) - _TIFFmemcpy(&dir[m].tdir_offset,data,datalength); - else - { - uint64 na,nb; - na=tif->tif_dataoff; - nb=na+datalength; - if (!(tif->tif_flags&TIFF_BIGTIFF)) - nb=(uint32)nb; - if ((nbtif_clientdata,module,"Maximum TIFF file size exceeded"); - return(0); - } - if (!SeekOK(tif,na)) - { - TIFFErrorExt(tif->tif_clientdata,module,"IO error writing tag data"); - return(0); - } - assert(datalength<0x80000000UL); - if (!WriteOK(tif,data,(tmsize_t)datalength)) - { - TIFFErrorExt(tif->tif_clientdata,module,"IO error writing tag data"); - return(0); - } - tif->tif_dataoff=nb; - if (tif->tif_dataoff&1) - tif->tif_dataoff++; - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - uint32 o; - o=(uint32)na; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong(&o); - _TIFFmemcpy(&dir[m].tdir_offset,&o,4); - } - else - { - dir[m].tdir_offset.toff_long8 = na; - if (tif->tif_flags&TIFF_SWAB) - TIFFSwabLong8(&dir[m].tdir_offset.toff_long8); - } - } - (*ndir)++; - return(1); + static const char module[] = "TIFFWriteDirectoryTagData"; + uint32 m; + m=0; + while (m<(*ndir)) + { + assert(dir[m].tdir_tag!=tag); + if (dir[m].tdir_tag>tag) + break; + m++; + } + if (m<(*ndir)) + { + uint32 n; + for (n=*ndir; n>m; n--) + dir[n]=dir[n-1]; + } + dir[m].tdir_tag=tag; + dir[m].tdir_type=datatype; + dir[m].tdir_count=count; + dir[m].tdir_offset.toff_long8 = 0; + if (datalength<=((tif->tif_flags&TIFF_BIGTIFF)?0x8U:0x4U)) + _TIFFmemcpy(&dir[m].tdir_offset,data,datalength); + else + { + uint64 na,nb; + na=tif->tif_dataoff; + nb=na+datalength; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + nb=(uint32)nb; + if ((nbtif_clientdata,module,"Maximum TIFF file size exceeded"); + return(0); + } + if (!SeekOK(tif,na)) + { + TIFFErrorExt(tif->tif_clientdata,module,"IO error writing tag data"); + return(0); + } + assert(datalength<0x80000000UL); + if (!WriteOK(tif,data,(tmsize_t)datalength)) + { + TIFFErrorExt(tif->tif_clientdata,module,"IO error writing tag data"); + return(0); + } + tif->tif_dataoff=nb; + if (tif->tif_dataoff&1) + tif->tif_dataoff++; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + uint32 o; + o=(uint32)na; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong(&o); + _TIFFmemcpy(&dir[m].tdir_offset,&o,4); + } + else + { + dir[m].tdir_offset.toff_long8 = na; + if (tif->tif_flags&TIFF_SWAB) + TIFFSwabLong8(&dir[m].tdir_offset.toff_long8); + } + } + (*ndir)++; + return(1); } /* @@ -2366,190 +2479,190 @@ TIFFWriteDirectoryTagData(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag static int TIFFLinkDirectory(TIFF* tif) { - static const char module[] = "TIFFLinkDirectory"; + static const char module[] = "TIFFLinkDirectory"; - tif->tif_diroff = (TIFFSeekFile(tif,0,SEEK_END)+1) &~ 1; + tif->tif_diroff = (TIFFSeekFile(tif,0,SEEK_END)+1) & (~((toff_t)1)); - /* - * Handle SubIFDs - */ - if (tif->tif_flags & TIFF_INSUBIFD) - { - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - uint32 m; - m = (uint32)tif->tif_diroff; - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong(&m); - (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET); - if (!WriteOK(tif, &m, 4)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error writing SubIFD directory link"); - return (0); - } - /* - * Advance to the next SubIFD or, if this is - * the last one configured, revert back to the - * normal directory linkage. - */ - if (--tif->tif_nsubifd) - tif->tif_subifdoff += 4; - else - tif->tif_flags &= ~TIFF_INSUBIFD; - return (1); - } - else - { - uint64 m; - m = tif->tif_diroff; - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(&m); - (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET); - if (!WriteOK(tif, &m, 8)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error writing SubIFD directory link"); - return (0); - } - /* - * Advance to the next SubIFD or, if this is - * the last one configured, revert back to the - * normal directory linkage. - */ - if (--tif->tif_nsubifd) - tif->tif_subifdoff += 8; - else - tif->tif_flags &= ~TIFF_INSUBIFD; - return (1); - } - } + /* + * Handle SubIFDs + */ + if (tif->tif_flags & TIFF_INSUBIFD) + { + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + uint32 m; + m = (uint32)tif->tif_diroff; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&m); + (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET); + if (!WriteOK(tif, &m, 4)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error writing SubIFD directory link"); + return (0); + } + /* + * Advance to the next SubIFD or, if this is + * the last one configured, revert back to the + * normal directory linkage. + */ + if (--tif->tif_nsubifd) + tif->tif_subifdoff += 4; + else + tif->tif_flags &= ~TIFF_INSUBIFD; + return (1); + } + else + { + uint64 m; + m = tif->tif_diroff; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8(&m); + (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET); + if (!WriteOK(tif, &m, 8)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error writing SubIFD directory link"); + return (0); + } + /* + * Advance to the next SubIFD or, if this is + * the last one configured, revert back to the + * normal directory linkage. + */ + if (--tif->tif_nsubifd) + tif->tif_subifdoff += 8; + else + tif->tif_flags &= ~TIFF_INSUBIFD; + return (1); + } + } - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - uint32 m; - uint32 nextdir; - m = (uint32)(tif->tif_diroff); - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong(&m); - if (tif->tif_header.classic.tiff_diroff == 0) { - /* - * First directory, overwrite offset in header. - */ - tif->tif_header.classic.tiff_diroff = (uint32) tif->tif_diroff; - (void) TIFFSeekFile(tif,4, SEEK_SET); - if (!WriteOK(tif, &m, 4)) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "Error writing TIFF header"); - return (0); - } - return (1); - } - /* - * Not the first directory, search to the last and append. - */ - nextdir = tif->tif_header.classic.tiff_diroff; - while(1) { - uint16 dircount; - uint32 nextnextdir; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + uint32 m; + uint32 nextdir; + m = (uint32)(tif->tif_diroff); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&m); + if (tif->tif_header.classic.tiff_diroff == 0) { + /* + * First directory, overwrite offset in header. + */ + tif->tif_header.classic.tiff_diroff = (uint32) tif->tif_diroff; + (void) TIFFSeekFile(tif,4, SEEK_SET); + if (!WriteOK(tif, &m, 4)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error writing TIFF header"); + return (0); + } + return (1); + } + /* + * Not the first directory, search to the last and append. + */ + nextdir = tif->tif_header.classic.tiff_diroff; + while(1) { + uint16 dircount; + uint32 nextnextdir; - if (!SeekOK(tif, nextdir) || - !ReadOK(tif, &dircount, 2)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error fetching directory count"); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabShort(&dircount); - (void) TIFFSeekFile(tif, - nextdir+2+dircount*12, SEEK_SET); - if (!ReadOK(tif, &nextnextdir, 4)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error fetching directory link"); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong(&nextnextdir); - if (nextnextdir==0) - { - (void) TIFFSeekFile(tif, - nextdir+2+dircount*12, SEEK_SET); - if (!WriteOK(tif, &m, 4)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error writing directory link"); - return (0); - } - break; - } - nextdir=nextnextdir; - } - } - else - { - uint64 m; - uint64 nextdir; - m = tif->tif_diroff; - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(&m); - if (tif->tif_header.big.tiff_diroff == 0) { - /* - * First directory, overwrite offset in header. - */ - tif->tif_header.big.tiff_diroff = tif->tif_diroff; - (void) TIFFSeekFile(tif,8, SEEK_SET); - if (!WriteOK(tif, &m, 8)) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "Error writing TIFF header"); - return (0); - } - return (1); - } - /* - * Not the first directory, search to the last and append. - */ - nextdir = tif->tif_header.big.tiff_diroff; - while(1) { - uint64 dircount64; - uint16 dircount; - uint64 nextnextdir; + if (!SeekOK(tif, nextdir) || + !ReadOK(tif, &dircount, 2)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory count"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&dircount); + (void) TIFFSeekFile(tif, + nextdir+2+dircount*12, SEEK_SET); + if (!ReadOK(tif, &nextnextdir, 4)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory link"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&nextnextdir); + if (nextnextdir==0) + { + (void) TIFFSeekFile(tif, + nextdir+2+dircount*12, SEEK_SET); + if (!WriteOK(tif, &m, 4)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error writing directory link"); + return (0); + } + break; + } + nextdir=nextnextdir; + } + } + else + { + uint64 m; + uint64 nextdir; + m = tif->tif_diroff; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8(&m); + if (tif->tif_header.big.tiff_diroff == 0) { + /* + * First directory, overwrite offset in header. + */ + tif->tif_header.big.tiff_diroff = tif->tif_diroff; + (void) TIFFSeekFile(tif,8, SEEK_SET); + if (!WriteOK(tif, &m, 8)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Error writing TIFF header"); + return (0); + } + return (1); + } + /* + * Not the first directory, search to the last and append. + */ + nextdir = tif->tif_header.big.tiff_diroff; + while(1) { + uint64 dircount64; + uint16 dircount; + uint64 nextnextdir; - if (!SeekOK(tif, nextdir) || - !ReadOK(tif, &dircount64, 8)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error fetching directory count"); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(&dircount64); - if (dircount64>0xFFFF) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Sanity check on tag count failed, likely corrupt TIFF"); - return (0); - } - dircount=(uint16)dircount64; - (void) TIFFSeekFile(tif, - nextdir+8+dircount*20, SEEK_SET); - if (!ReadOK(tif, &nextnextdir, 8)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error fetching directory link"); - return (0); - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(&nextnextdir); - if (nextnextdir==0) - { - (void) TIFFSeekFile(tif, - nextdir+8+dircount*20, SEEK_SET); - if (!WriteOK(tif, &m, 8)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error writing directory link"); - return (0); - } - break; - } - nextdir=nextnextdir; - } - } - return (1); + if (!SeekOK(tif, nextdir) || + !ReadOK(tif, &dircount64, 8)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory count"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8(&dircount64); + if (dircount64>0xFFFF) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Sanity check on tag count failed, likely corrupt TIFF"); + return (0); + } + dircount=(uint16)dircount64; + (void) TIFFSeekFile(tif, + nextdir+8+dircount*20, SEEK_SET); + if (!ReadOK(tif, &nextnextdir, 8)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error fetching directory link"); + return (0); + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8(&nextnextdir); + if (nextnextdir==0) + { + (void) TIFFSeekFile(tif, + nextdir+8+dircount*20, SEEK_SET); + if (!WriteOK(tif, &m, 8)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error writing directory link"); + return (0); + } + break; + } + nextdir=nextnextdir; + } + } + return (1); } /************************************************************************/ @@ -2566,11 +2679,11 @@ TIFFLinkDirectory(TIFF* tif) /************************************************************************/ int -_TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, +_TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, tmsize_t count, void* data) { static const char module[] = "TIFFResetField"; - const TIFFField* fip = NULL; + /* const TIFFField* fip = NULL; */ uint16 dircount; tmsize_t dirsize; uint8 direntry_raw[20]; @@ -2586,21 +2699,21 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, /* -------------------------------------------------------------------- */ /* Find field definition. */ /* -------------------------------------------------------------------- */ - fip = TIFFFindField(tif, tag, TIFF_ANY); + /*fip =*/ TIFFFindField(tif, tag, TIFF_ANY); /* -------------------------------------------------------------------- */ /* Do some checking this is a straight forward case. */ /* -------------------------------------------------------------------- */ if( isMapped(tif) ) { - TIFFErrorExt( tif->tif_clientdata, module, + TIFFErrorExt( tif->tif_clientdata, module, "Memory mapped files not currently supported for this operation." ); return 0; } if( tif->tif_diroff == 0 ) { - TIFFErrorExt( tif->tif_clientdata, module, + TIFFErrorExt( tif->tif_clientdata, module, "Attempt to reset field on directory not already on disk." ); return 0; } @@ -2684,7 +2797,7 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, if (!(tif->tif_flags&TIFF_BIGTIFF)) { uint32 value; - + memcpy( &value, direntry_raw + 4, sizeof(uint32) ); if (tif->tif_flags&TIFF_SWAB) TIFFSwabLong( &value ); @@ -2720,7 +2833,7 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, else datatype = in_datatype; } - else + else datatype = in_datatype; /* -------------------------------------------------------------------- */ @@ -2728,8 +2841,8 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, /* swabbing as needed. */ /* -------------------------------------------------------------------- */ buf_to_write = - (uint8 *)_TIFFCheckMalloc(tif, count, TIFFDataWidth(datatype), - "for field buffer."); + (uint8 *)_TIFFCheckMalloc(tif, count, TIFFDataWidth(datatype), + "for field buffer."); if (!buf_to_write) return 0; @@ -2737,16 +2850,16 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, memcpy( buf_to_write, data, count * TIFFDataWidth(datatype) ); else if( datatype == TIFF_SLONG && in_datatype == TIFF_SLONG8 ) { - tmsize_t i; + tmsize_t i; for( i = 0; i < count; i++ ) { - ((int32 *) buf_to_write)[i] = + ((int32 *) buf_to_write)[i] = (int32) ((int64 *) data)[i]; if( (int64) ((int32 *) buf_to_write)[i] != ((int64 *) data)[i] ) { _TIFFfree( buf_to_write ); - TIFFErrorExt( tif->tif_clientdata, module, + TIFFErrorExt( tif->tif_clientdata, module, "Value exceeds 32bit range of output type." ); return 0; } @@ -2755,16 +2868,16 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, else if( (datatype == TIFF_LONG && in_datatype == TIFF_LONG8) || (datatype == TIFF_IFD && in_datatype == TIFF_IFD8) ) { - tmsize_t i; + tmsize_t i; for( i = 0; i < count; i++ ) { - ((uint32 *) buf_to_write)[i] = + ((uint32 *) buf_to_write)[i] = (uint32) ((uint64 *) data)[i]; if( (uint64) ((uint32 *) buf_to_write)[i] != ((uint64 *) data)[i] ) { _TIFFfree( buf_to_write ); - TIFFErrorExt( tif->tif_clientdata, module, + TIFFErrorExt( tif->tif_clientdata, module, "Value exceeds 32bit range of output type." ); return 0; } @@ -2832,21 +2945,22 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, if( !value_in_entry ) { entry_offset = TIFFSeekFile(tif,0,SEEK_END); - + if (!WriteOK(tif, buf_to_write, count*TIFFDataWidth(datatype))) { _TIFFfree( buf_to_write ); TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); return (0); } - - _TIFFfree( buf_to_write ); } else { memcpy( &entry_offset, buf_to_write, count*TIFFDataWidth(datatype)); } + _TIFFfree( buf_to_write ); + buf_to_write = 0; + /* -------------------------------------------------------------------- */ /* Adjust the directory entry. */ /* -------------------------------------------------------------------- */ @@ -2897,7 +3011,7 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, tif->tif_name); return 0; } - + return 1; } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_dumpmode.c b/3rdparty/libtiff/tif_dumpmode.c index de482b433b..a6a94c04d5 100644 --- a/3rdparty/libtiff/tif_dumpmode.c +++ b/3rdparty/libtiff/tif_dumpmode.c @@ -1,26 +1,26 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dumpmode.c,v 1.14 2011-04-02 20:54:09 bfriesen Exp $ */ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_dumpmode.c,v 1.15 2015-12-12 18:04:26 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -34,8 +34,8 @@ static int DumpFixupTags(TIFF* tif) { - (void) tif; - return (1); + (void) tif; + return (1); } /* @@ -44,31 +44,31 @@ DumpFixupTags(TIFF* tif) static int DumpModeEncode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s) { - (void) s; - while (cc > 0) { - tmsize_t n; + (void) s; + while (cc > 0) { + tmsize_t n; - n = cc; - if (tif->tif_rawcc + n > tif->tif_rawdatasize) - n = tif->tif_rawdatasize - tif->tif_rawcc; + n = cc; + if (tif->tif_rawcc + n > tif->tif_rawdatasize) + n = tif->tif_rawdatasize - tif->tif_rawcc; - assert( n > 0 ); + assert( n > 0 ); - /* - * Avoid copy if client has setup raw - * data buffer to avoid extra copy. - */ - if (tif->tif_rawcp != pp) - _TIFFmemcpy(tif->tif_rawcp, pp, n); - tif->tif_rawcp += n; - tif->tif_rawcc += n; - pp += n; - cc -= n; - if (tif->tif_rawcc >= tif->tif_rawdatasize && - !TIFFFlushData1(tif)) - return (-1); - } - return (1); + /* + * Avoid copy if client has setup raw + * data buffer to avoid extra copy. + */ + if (tif->tif_rawcp != pp) + _TIFFmemcpy(tif->tif_rawcp, pp, n); + tif->tif_rawcp += n; + tif->tif_rawcc += n; + pp += n; + cc -= n; + if (tif->tif_rawcc >= tif->tif_rawdatasize && + !TIFFFlushData1(tif)) + return (0); + } + return (1); } /* @@ -77,33 +77,33 @@ DumpModeEncode(TIFF* tif, uint8* pp, tmsize_t cc, uint16 s) static int DumpModeDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) { - static const char module[] = "DumpModeDecode"; - (void) s; - if (tif->tif_rawcc < cc) { + static const char module[] = "DumpModeDecode"; + (void) s; + if (tif->tif_rawcc < cc) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, + TIFFErrorExt(tif->tif_clientdata, module, "Not enough data for scanline %lu, expected a request for at most %I64d bytes, got a request for %I64d bytes", - (unsigned long) tif->tif_row, - (signed __int64) tif->tif_rawcc, - (signed __int64) cc); + (unsigned long) tif->tif_row, + (signed __int64) tif->tif_rawcc, + (signed __int64) cc); #else - TIFFErrorExt(tif->tif_clientdata, module, + TIFFErrorExt(tif->tif_clientdata, module, "Not enough data for scanline %lu, expected a request for at most %lld bytes, got a request for %lld bytes", - (unsigned long) tif->tif_row, - (signed long long) tif->tif_rawcc, - (signed long long) cc); + (unsigned long) tif->tif_row, + (signed long long) tif->tif_rawcc, + (signed long long) cc); #endif - return (0); - } - /* - * Avoid copy if client has setup raw - * data buffer to avoid extra copy. - */ - if (tif->tif_rawcp != buf) - _TIFFmemcpy(buf, tif->tif_rawcp, cc); - tif->tif_rawcp += cc; - tif->tif_rawcc -= cc; - return (1); + return (0); + } + /* + * Avoid copy if client has setup raw + * data buffer to avoid extra copy. + */ + if (tif->tif_rawcp != buf) + _TIFFmemcpy(buf, tif->tif_rawcp, cc); + tif->tif_rawcp += cc; + tif->tif_rawcc -= cc; + return (1); } /* @@ -112,9 +112,9 @@ DumpModeDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) static int DumpModeSeek(TIFF* tif, uint32 nrows) { - tif->tif_rawcp += nrows * tif->tif_scanlinesize; - tif->tif_rawcc -= nrows * tif->tif_scanlinesize; - return (1); + tif->tif_rawcp += nrows * tif->tif_scanlinesize; + tif->tif_rawcc -= nrows * tif->tif_scanlinesize; + return (1); } /* @@ -123,16 +123,16 @@ DumpModeSeek(TIFF* tif, uint32 nrows) int TIFFInitDumpMode(TIFF* tif, int scheme) { - (void) scheme; - tif->tif_fixuptags = DumpFixupTags; - tif->tif_decoderow = DumpModeDecode; - tif->tif_decodestrip = DumpModeDecode; - tif->tif_decodetile = DumpModeDecode; - tif->tif_encoderow = DumpModeEncode; - tif->tif_encodestrip = DumpModeEncode; - tif->tif_encodetile = DumpModeEncode; - tif->tif_seek = DumpModeSeek; - return (1); + (void) scheme; + tif->tif_fixuptags = DumpFixupTags; + tif->tif_decoderow = DumpModeDecode; + tif->tif_decodestrip = DumpModeDecode; + tif->tif_decodetile = DumpModeDecode; + tif->tif_encoderow = DumpModeEncode; + tif->tif_encodestrip = DumpModeEncode; + tif->tif_encodetile = DumpModeEncode; + tif->tif_seek = DumpModeSeek; + return (1); } /* * Local Variables: diff --git a/3rdparty/libtiff/tif_error.c b/3rdparty/libtiff/tif_error.c index 886ee0dfe6..47516b4f59 100644 --- a/3rdparty/libtiff/tif_error.c +++ b/3rdparty/libtiff/tif_error.c @@ -1,26 +1,26 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_error.c,v 1.5 2010-03-10 18:56:48 bfriesen Exp $ */ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_error.c,v 1.6 2017-07-04 12:54:42 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -34,41 +34,49 @@ TIFFErrorHandlerExt _TIFFerrorHandlerExt = NULL; TIFFErrorHandler TIFFSetErrorHandler(TIFFErrorHandler handler) { - TIFFErrorHandler prev = _TIFFerrorHandler; - _TIFFerrorHandler = handler; - return (prev); + TIFFErrorHandler prev = _TIFFerrorHandler; + _TIFFerrorHandler = handler; + return (prev); } TIFFErrorHandlerExt TIFFSetErrorHandlerExt(TIFFErrorHandlerExt handler) { - TIFFErrorHandlerExt prev = _TIFFerrorHandlerExt; - _TIFFerrorHandlerExt = handler; - return (prev); + TIFFErrorHandlerExt prev = _TIFFerrorHandlerExt; + _TIFFerrorHandlerExt = handler; + return (prev); } void TIFFError(const char* module, const char* fmt, ...) { - va_list ap; - va_start(ap, fmt); - if (_TIFFerrorHandler) - (*_TIFFerrorHandler)(module, fmt, ap); - if (_TIFFerrorHandlerExt) - (*_TIFFerrorHandlerExt)(0, module, fmt, ap); - va_end(ap); + va_list ap; + if (_TIFFerrorHandler) { + va_start(ap, fmt); + (*_TIFFerrorHandler)(module, fmt, ap); + va_end(ap); + } + if (_TIFFerrorHandlerExt) { + va_start(ap, fmt); + (*_TIFFerrorHandlerExt)(0, module, fmt, ap); + va_end(ap); + } } void TIFFErrorExt(thandle_t fd, const char* module, const char* fmt, ...) { - va_list ap; - va_start(ap, fmt); - if (_TIFFerrorHandler) - (*_TIFFerrorHandler)(module, fmt, ap); - if (_TIFFerrorHandlerExt) - (*_TIFFerrorHandlerExt)(fd, module, fmt, ap); - va_end(ap); + va_list ap; + if (_TIFFerrorHandler) { + va_start(ap, fmt); + (*_TIFFerrorHandler)(module, fmt, ap); + va_end(ap); + } + if (_TIFFerrorHandlerExt) { + va_start(ap, fmt); + (*_TIFFerrorHandlerExt)(fd, module, fmt, ap); + va_end(ap); + } } /* diff --git a/3rdparty/libtiff/tif_extension.c b/3rdparty/libtiff/tif_extension.c index d013c69cbf..39fab4c7ba 100644 --- a/3rdparty/libtiff/tif_extension.c +++ b/3rdparty/libtiff/tif_extension.c @@ -1,26 +1,26 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_extension.c,v 1.7 2010-03-10 18:56:48 bfriesen Exp $ */ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_extension.c,v 1.8 2015-12-06 11:13:43 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -28,7 +28,7 @@ * TIFF Library. * * Various routines support external extension of the tag set, and other - * application extension capabilities. + * application extension capabilities. */ #include "tiffiop.h" @@ -37,7 +37,7 @@ int TIFFGetTagListCount( TIFF *tif ) { TIFFDirectory* td = &tif->tif_dir; - + return td->td_customValueCount; } @@ -66,13 +66,13 @@ TIFFTagMethods *TIFFAccessTagMethods( TIFF *tif ) void *TIFFGetClientInfo( TIFF *tif, const char *name ) { - TIFFClientInfoLink *link = tif->tif_clientinfo; + TIFFClientInfoLink *psLink = tif->tif_clientinfo; - while( link != NULL && strcmp(link->name,name) != 0 ) - link = link->next; + while( psLink != NULL && strcmp(psLink->name,name) != 0 ) + psLink = psLink->next; - if( link != NULL ) - return link->data; + if( psLink != NULL ) + return psLink->data; else return NULL; } @@ -80,18 +80,18 @@ void *TIFFGetClientInfo( TIFF *tif, const char *name ) void TIFFSetClientInfo( TIFF *tif, void *data, const char *name ) { - TIFFClientInfoLink *link = tif->tif_clientinfo; + TIFFClientInfoLink *psLink = tif->tif_clientinfo; /* ** Do we have an existing link with this name? If so, just ** set it. */ - while( link != NULL && strcmp(link->name,name) != 0 ) - link = link->next; + while( psLink != NULL && strcmp(psLink->name,name) != 0 ) + psLink = psLink->next; - if( link != NULL ) + if( psLink != NULL ) { - link->data = data; + psLink->data = data; return; } @@ -99,15 +99,15 @@ void TIFFSetClientInfo( TIFF *tif, void *data, const char *name ) ** Create a new link. */ - link = (TIFFClientInfoLink *) _TIFFmalloc(sizeof(TIFFClientInfoLink)); - assert (link != NULL); - link->next = tif->tif_clientinfo; - link->name = (char *) _TIFFmalloc((tmsize_t)(strlen(name)+1)); - assert (link->name != NULL); - strcpy(link->name, name); - link->data = data; + psLink = (TIFFClientInfoLink *) _TIFFmalloc(sizeof(TIFFClientInfoLink)); + assert (psLink != NULL); + psLink->next = tif->tif_clientinfo; + psLink->name = (char *) _TIFFmalloc((tmsize_t)(strlen(name)+1)); + assert (psLink->name != NULL); + strcpy(psLink->name, name); + psLink->data = data; - tif->tif_clientinfo = link; + tif->tif_clientinfo = psLink; } /* * Local Variables: diff --git a/3rdparty/libtiff/tif_fax3.c b/3rdparty/libtiff/tif_fax3.c index 5e839b7ae7..5fd514118c 100644 --- a/3rdparty/libtiff/tif_fax3.c +++ b/3rdparty/libtiff/tif_fax3.c @@ -1,26 +1,26 @@ -/* $Id: tif_fax3.c,v 1.73 2012-06-13 00:27:20 fwarmerdam Exp $ */ +/* $Id: tif_fax3.c,v 1.81 2017-06-18 10:31:50 erouault Exp $ */ /* * Copyright (c) 1990-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -48,43 +48,43 @@ * derived from this ``base state'' block. */ typedef struct { - int rw_mode; /* O_RDONLY for decode, else encode */ - int mode; /* operating mode */ - tmsize_t rowbytes; /* bytes in a decoded scanline */ - uint32 rowpixels; /* pixels in a scanline */ + int rw_mode; /* O_RDONLY for decode, else encode */ + int mode; /* operating mode */ + tmsize_t rowbytes; /* bytes in a decoded scanline */ + uint32 rowpixels; /* pixels in a scanline */ - uint16 cleanfaxdata; /* CleanFaxData tag */ - uint32 badfaxrun; /* BadFaxRun tag */ - uint32 badfaxlines; /* BadFaxLines tag */ - uint32 groupoptions; /* Group 3/4 options tag */ + uint16 cleanfaxdata; /* CleanFaxData tag */ + uint32 badfaxrun; /* BadFaxRun tag */ + uint32 badfaxlines; /* BadFaxLines tag */ + uint32 groupoptions; /* Group 3/4 options tag */ - TIFFVGetMethod vgetparent; /* super-class method */ - TIFFVSetMethod vsetparent; /* super-class method */ - TIFFPrintMethod printdir; /* super-class method */ + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + TIFFPrintMethod printdir; /* super-class method */ } Fax3BaseState; #define Fax3State(tif) ((Fax3BaseState*) (tif)->tif_data) typedef enum { G3_1D, G3_2D } Ttag; typedef struct { - Fax3BaseState b; + Fax3BaseState b; - /* Decoder state info */ - const unsigned char* bitmap; /* bit reversal table */ - uint32 data; /* current i/o byte/word */ - int bit; /* current i/o bit in byte */ - int EOLcnt; /* count of EOL codes recognized */ - TIFFFaxFillFunc fill; /* fill routine */ - uint32* runs; /* b&w runs for current/previous row */ - uint32* refruns; /* runs for reference line */ - uint32* curruns; /* runs for current line */ + /* Decoder state info */ + const unsigned char* bitmap; /* bit reversal table */ + uint32 data; /* current i/o byte/word */ + int bit; /* current i/o bit in byte */ + int EOLcnt; /* count of EOL codes recognized */ + TIFFFaxFillFunc fill; /* fill routine */ + uint32* runs; /* b&w runs for current/previous row */ + uint32* refruns; /* runs for reference line */ + uint32* curruns; /* runs for current line */ - /* Encoder state info */ - Ttag tag; /* encoding state */ - unsigned char* refline; /* reference line for 2d decoding */ - int k; /* #rows left that can be 2d encoded */ - int maxk; /* max #rows that can be 2d encoded */ + /* Encoder state info */ + Ttag tag; /* encoding state */ + unsigned char* refline; /* reference line for 2d decoding */ + int k; /* #rows left that can be 2d encoded */ + int maxk; /* max #rows that can be 2d encoded */ - int line; + int line; } Fax3CodecState; #define DecoderState(tif) ((Fax3CodecState*) Fax3State(tif)) #define EncoderState(tif) ((Fax3CodecState*) Fax3State(tif)) @@ -146,28 +146,28 @@ typedef struct { static int Fax3PreDecode(TIFF* tif, uint16 s) { - Fax3CodecState* sp = DecoderState(tif); + Fax3CodecState* sp = DecoderState(tif); - (void) s; - assert(sp != NULL); - sp->bit = 0; /* force initial read */ - sp->data = 0; - sp->EOLcnt = 0; /* force initial scan for EOL */ - /* - * Decoder assumes lsb-to-msb bit order. Note that we select - * this here rather than in Fax3SetupState so that viewers can - * hold the image open, fiddle with the FillOrder tag value, - * and then re-decode the image. Otherwise they'd need to close - * and open the image to get the state reset. - */ - sp->bitmap = - TIFFGetBitRevTable(tif->tif_dir.td_fillorder != FILLORDER_LSB2MSB); - if (sp->refruns) { /* init reference line to white */ - sp->refruns[0] = (uint32) sp->b.rowpixels; - sp->refruns[1] = 0; - } - sp->line = 0; - return (1); + (void) s; + assert(sp != NULL); + sp->bit = 0; /* force initial read */ + sp->data = 0; + sp->EOLcnt = 0; /* force initial scan for EOL */ + /* + * Decoder assumes lsb-to-msb bit order. Note that we select + * this here rather than in Fax3SetupState so that viewers can + * hold the image open, fiddle with the FillOrder tag value, + * and then re-decode the image. Otherwise they'd need to close + * and open the image to get the state reset. + */ + sp->bitmap = + TIFFGetBitRevTable(tif->tif_dir.td_fillorder != FILLORDER_LSB2MSB); + if (sp->refruns) { /* init reference line to white */ + sp->refruns[0] = (uint32) sp->b.rowpixels; + sp->refruns[1] = 0; + } + sp->line = 0; + return (1); } /* @@ -179,42 +179,42 @@ Fax3PreDecode(TIFF* tif, uint16 s) static void Fax3Unexpected(const char* module, TIFF* tif, uint32 line, uint32 a0) { - TIFFErrorExt(tif->tif_clientdata, module, "Bad code word at line %u of %s %u (x %u)", - line, isTiled(tif) ? "tile" : "strip", - (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), - a0); + TIFFErrorExt(tif->tif_clientdata, module, "Bad code word at line %u of %s %u (x %u)", + line, isTiled(tif) ? "tile" : "strip", + (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), + a0); } #define unexpected(table, a0) Fax3Unexpected(module, tif, sp->line, a0) static void Fax3Extension(const char* module, TIFF* tif, uint32 line, uint32 a0) { - TIFFErrorExt(tif->tif_clientdata, module, - "Uncompressed data (not supported) at line %u of %s %u (x %u)", - line, isTiled(tif) ? "tile" : "strip", - (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), - a0); + TIFFErrorExt(tif->tif_clientdata, module, + "Uncompressed data (not supported) at line %u of %s %u (x %u)", + line, isTiled(tif) ? "tile" : "strip", + (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), + a0); } #define extension(a0) Fax3Extension(module, tif, sp->line, a0) static void Fax3BadLength(const char* module, TIFF* tif, uint32 line, uint32 a0, uint32 lastx) { - TIFFWarningExt(tif->tif_clientdata, module, "%s at line %u of %s %u (got %u, expected %u)", - a0 < lastx ? "Premature EOL" : "Line length mismatch", - line, isTiled(tif) ? "tile" : "strip", - (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), - a0, lastx); + TIFFWarningExt(tif->tif_clientdata, module, "%s at line %u of %s %u (got %u, expected %u)", + a0 < lastx ? "Premature EOL" : "Line length mismatch", + line, isTiled(tif) ? "tile" : "strip", + (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), + a0, lastx); } #define badlength(a0,lastx) Fax3BadLength(module, tif, sp->line, a0, lastx) static void Fax3PrematureEOF(const char* module, TIFF* tif, uint32 line, uint32 a0) { - TIFFWarningExt(tif->tif_clientdata, module, "Premature EOF at line %u of %s %u (x %u)", - line, isTiled(tif) ? "tile" : "strip", - (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), - a0); + TIFFWarningExt(tif->tif_clientdata, module, "Premature EOF at line %u of %s %u (x %u)", + line, isTiled(tif) ? "tile" : "strip", + (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), + a0); } #define prematureEOF(a0) Fax3PrematureEOF(module, tif, sp->line, a0) @@ -226,40 +226,40 @@ Fax3PrematureEOF(const char* module, TIFF* tif, uint32 line, uint32 a0) static int Fax3Decode1D(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) { - DECLARE_STATE(tif, sp, "Fax3Decode1D"); - (void) s; - if (occ % sp->b.rowbytes) - { - TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); - return (-1); - } - CACHE_STATE(tif, sp); - thisrun = sp->curruns; - while (occ > 0) { - a0 = 0; - RunLength = 0; - pa = thisrun; + DECLARE_STATE(tif, sp, "Fax3Decode1D"); + (void) s; + if (occ % sp->b.rowbytes) + { + TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); + return (-1); + } + CACHE_STATE(tif, sp); + thisrun = sp->curruns; + while (occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun; #ifdef FAX3_DEBUG - printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); - printf("-------------------- %d\n", tif->tif_row); - fflush(stdout); + printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", tif->tif_row); + fflush(stdout); #endif - SYNC_EOL(EOF1D); - EXPAND1D(EOF1Da); - (*sp->fill)(buf, thisrun, pa, lastx); - buf += sp->b.rowbytes; - occ -= sp->b.rowbytes; - sp->line++; - continue; - EOF1D: /* premature EOF */ - CLEANUP_RUNS(); - EOF1Da: /* premature EOF */ - (*sp->fill)(buf, thisrun, pa, lastx); - UNCACHE_STATE(tif, sp); - return (-1); - } - UNCACHE_STATE(tif, sp); - return (1); + SYNC_EOL(EOF1D); + EXPAND1D(EOF1Da); + (*sp->fill)(buf, thisrun, pa, lastx); + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + sp->line++; + continue; + EOF1D: /* premature EOF */ + CLEANUP_RUNS(); + EOF1Da: /* premature EOF */ + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return (-1); + } + UNCACHE_STATE(tif, sp); + return (1); } #define SWAP(t,a,b) { t x; x = (a); (a) = (b); (b) = x; } @@ -269,54 +269,54 @@ Fax3Decode1D(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) static int Fax3Decode2D(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) { - DECLARE_STATE_2D(tif, sp, "Fax3Decode2D"); - int is1D; /* current line is 1d/2d-encoded */ - (void) s; - if (occ % sp->b.rowbytes) - { - TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); - return (-1); - } - CACHE_STATE(tif, sp); - while (occ > 0) { - a0 = 0; - RunLength = 0; - pa = thisrun = sp->curruns; + DECLARE_STATE_2D(tif, sp, "Fax3Decode2D"); + int is1D; /* current line is 1d/2d-encoded */ + (void) s; + if (occ % sp->b.rowbytes) + { + TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); + return (-1); + } + CACHE_STATE(tif, sp); + while (occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun = sp->curruns; #ifdef FAX3_DEBUG - printf("\nBitAcc=%08X, BitsAvail = %d EOLcnt = %d", - BitAcc, BitsAvail, EOLcnt); + printf("\nBitAcc=%08X, BitsAvail = %d EOLcnt = %d", + BitAcc, BitsAvail, EOLcnt); #endif - SYNC_EOL(EOF2D); - NeedBits8(1, EOF2D); - is1D = GetBits(1); /* 1D/2D-encoding tag bit */ - ClrBits(1); + SYNC_EOL(EOF2D); + NeedBits8(1, EOF2D); + is1D = GetBits(1); /* 1D/2D-encoding tag bit */ + ClrBits(1); #ifdef FAX3_DEBUG - printf(" %s\n-------------------- %d\n", - is1D ? "1D" : "2D", tif->tif_row); - fflush(stdout); + printf(" %s\n-------------------- %d\n", + is1D ? "1D" : "2D", tif->tif_row); + fflush(stdout); #endif - pb = sp->refruns; - b1 = *pb++; - if (is1D) - EXPAND1D(EOF2Da); - else - EXPAND2D(EOF2Da); - (*sp->fill)(buf, thisrun, pa, lastx); - SETVALUE(0); /* imaginary change for reference */ - SWAP(uint32*, sp->curruns, sp->refruns); - buf += sp->b.rowbytes; - occ -= sp->b.rowbytes; - sp->line++; - continue; - EOF2D: /* premature EOF */ - CLEANUP_RUNS(); - EOF2Da: /* premature EOF */ - (*sp->fill)(buf, thisrun, pa, lastx); - UNCACHE_STATE(tif, sp); - return (-1); - } - UNCACHE_STATE(tif, sp); - return (1); + pb = sp->refruns; + b1 = *pb++; + if (is1D) + EXPAND1D(EOF2Da); + else + EXPAND2D(EOF2Da); + (*sp->fill)(buf, thisrun, pa, lastx); + SETVALUE(0); /* imaginary change for reference */ + SWAP(uint32*, sp->curruns, sp->refruns); + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + sp->line++; + continue; + EOF2D: /* premature EOF */ + CLEANUP_RUNS(); + EOF2Da: /* premature EOF */ + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return (-1); + } + UNCACHE_STATE(tif, sp); + return (1); } #undef SWAP @@ -329,34 +329,64 @@ Fax3Decode2D(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) #if SIZEOF_UNSIGNED_LONG == 8 # define FILL(n, cp) \ switch (n) { \ - case 15:(cp)[14] = 0xff; case 14:(cp)[13] = 0xff; case 13: (cp)[12] = 0xff;\ - case 12:(cp)[11] = 0xff; case 11:(cp)[10] = 0xff; case 10: (cp)[9] = 0xff;\ - case 9: (cp)[8] = 0xff; case 8: (cp)[7] = 0xff; case 7: (cp)[6] = 0xff;\ - case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; case 4: (cp)[3] = 0xff;\ - case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \ - case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \ + case 15:(cp)[14] = 0xff; /*-fallthrough*/ \ + case 14:(cp)[13] = 0xff; /*-fallthrough*/ \ + case 13:(cp)[12] = 0xff; /*-fallthrough*/ \ + case 12:(cp)[11] = 0xff; /*-fallthrough*/ \ + case 11:(cp)[10] = 0xff; /*-fallthrough*/ \ + case 10: (cp)[9] = 0xff; /*-fallthrough*/ \ + case 9: (cp)[8] = 0xff; /*-fallthrough*/ \ + case 8: (cp)[7] = 0xff; /*-fallthrough*/ \ + case 7: (cp)[6] = 0xff; /*-fallthrough*/ \ + case 6: (cp)[5] = 0xff; /*-fallthrough*/ \ + case 5: (cp)[4] = 0xff; /*-fallthrough*/ \ + case 4: (cp)[3] = 0xff; /*-fallthrough*/ \ + case 3: (cp)[2] = 0xff; /*-fallthrough*/ \ + case 2: (cp)[1] = 0xff; /*-fallthrough*/ \ + case 1: (cp)[0] = 0xff; (cp) += (n); /*-fallthrough*/ \ + case 0: ; \ } # define ZERO(n, cp) \ switch (n) { \ - case 15:(cp)[14] = 0; case 14:(cp)[13] = 0; case 13: (cp)[12] = 0; \ - case 12:(cp)[11] = 0; case 11:(cp)[10] = 0; case 10: (cp)[9] = 0; \ - case 9: (cp)[8] = 0; case 8: (cp)[7] = 0; case 7: (cp)[6] = 0; \ - case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; case 4: (cp)[3] = 0; \ - case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \ - case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \ + case 15:(cp)[14] = 0; /*-fallthrough*/ \ + case 14:(cp)[13] = 0; /*-fallthrough*/ \ + case 13:(cp)[12] = 0; /*-fallthrough*/ \ + case 12:(cp)[11] = 0; /*-fallthrough*/ \ + case 11:(cp)[10] = 0; /*-fallthrough*/ \ + case 10: (cp)[9] = 0; /*-fallthrough*/ \ + case 9: (cp)[8] = 0; /*-fallthrough*/ \ + case 8: (cp)[7] = 0; /*-fallthrough*/ \ + case 7: (cp)[6] = 0; /*-fallthrough*/ \ + case 6: (cp)[5] = 0; /*-fallthrough*/ \ + case 5: (cp)[4] = 0; /*-fallthrough*/ \ + case 4: (cp)[3] = 0; /*-fallthrough*/ \ + case 3: (cp)[2] = 0; /*-fallthrough*/ \ + case 2: (cp)[1] = 0; /*-fallthrough*/ \ + case 1: (cp)[0] = 0; (cp) += (n); /*-fallthrough*/ \ + case 0: ; \ } #else # define FILL(n, cp) \ switch (n) { \ - case 7: (cp)[6] = 0xff; case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; \ - case 4: (cp)[3] = 0xff; case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \ - case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \ + case 7: (cp)[6] = 0xff; /*-fallthrough*/ \ + case 6: (cp)[5] = 0xff; /*-fallthrough*/ \ + case 5: (cp)[4] = 0xff; /*-fallthrough*/ \ + case 4: (cp)[3] = 0xff; /*-fallthrough*/ \ + case 3: (cp)[2] = 0xff; /*-fallthrough*/ \ + case 2: (cp)[1] = 0xff; /*-fallthrough*/ \ + case 1: (cp)[0] = 0xff; (cp) += (n); /*-fallthrough*/ \ + case 0: ; \ } # define ZERO(n, cp) \ switch (n) { \ - case 7: (cp)[6] = 0; case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; \ - case 4: (cp)[3] = 0; case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \ - case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \ + case 7: (cp)[6] = 0; /*-fallthrough*/ \ + case 6: (cp)[5] = 0; /*-fallthrough*/ \ + case 5: (cp)[4] = 0; /*-fallthrough*/ \ + case 4: (cp)[3] = 0; /*-fallthrough*/ \ + case 3: (cp)[2] = 0; /*-fallthrough*/ \ + case 2: (cp)[1] = 0; /*-fallthrough*/ \ + case 1: (cp)[0] = 0; (cp) += (n); /*-fallthrough*/ \ + case 0: ; \ } #endif @@ -367,89 +397,90 @@ Fax3Decode2D(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) void _TIFFFax3fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx) { - static const unsigned char _fillmasks[] = - { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; - unsigned char* cp; - uint32 x, bx, run; - int32 n, nw; - long* lp; + static const unsigned char _fillmasks[] = + { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; + unsigned char* cp; + uint32 x, bx, run; + int32 n, nw; + long* lp; - if ((erun-runs)&1) - *erun++ = 0; - x = 0; - for (; runs < erun; runs += 2) { - run = runs[0]; - if (x+run > lastx || run > lastx ) - run = runs[0] = (uint32) (lastx - x); - if (run) { - cp = buf + (x>>3); - bx = x&7; - if (run > 8-bx) { - if (bx) { /* align to byte boundary */ - *cp++ &= 0xff << (8-bx); - run -= 8-bx; - } - if( (n = run >> 3) != 0 ) { /* multiple bytes to fill */ - if ((n/sizeof (long)) > 1) { - /* - * Align to longword boundary and fill. - */ - for (; n && !isAligned(cp, long); n--) - *cp++ = 0x00; - lp = (long*) cp; - nw = (int32)(n / sizeof (long)); - n -= nw * sizeof (long); - do { - *lp++ = 0L; - } while (--nw); - cp = (unsigned char*) lp; - } - ZERO(n, cp); - run &= 7; - } - if (run) - cp[0] &= 0xff >> run; - } else - cp[0] &= ~(_fillmasks[run]>>bx); - x += runs[0]; - } - run = runs[1]; - if (x+run > lastx || run > lastx ) - run = runs[1] = lastx - x; - if (run) { - cp = buf + (x>>3); - bx = x&7; - if (run > 8-bx) { - if (bx) { /* align to byte boundary */ - *cp++ |= 0xff >> bx; - run -= 8-bx; - } - if( (n = run>>3) != 0 ) { /* multiple bytes to fill */ - if ((n/sizeof (long)) > 1) { - /* - * Align to longword boundary and fill. - */ - for (; n && !isAligned(cp, long); n--) - *cp++ = 0xff; - lp = (long*) cp; - nw = (int32)(n / sizeof (long)); - n -= nw * sizeof (long); - do { - *lp++ = -1L; - } while (--nw); - cp = (unsigned char*) lp; - } - FILL(n, cp); - run &= 7; - } - if (run) - cp[0] |= 0xff00 >> run; - } else - cp[0] |= _fillmasks[run]>>bx; - x += runs[1]; - } - } - assert(x == lastx); + if ((erun-runs)&1) + *erun++ = 0; + x = 0; + for (; runs < erun; runs += 2) { + run = runs[0]; + if (x+run > lastx || run > lastx ) + run = runs[0] = (uint32) (lastx - x); + if (run) { + cp = buf + (x>>3); + bx = x&7; + if (run > 8-bx) { + if (bx) { /* align to byte boundary */ + *cp++ &= 0xff << (8-bx); + run -= 8-bx; + } + if( (n = run >> 3) != 0 ) { /* multiple bytes to fill */ + if ((n/sizeof (long)) > 1) { + /* + * Align to longword boundary and fill. + */ + for (; n && !isAligned(cp, long); n--) + *cp++ = 0x00; + lp = (long*) cp; + nw = (int32)(n / sizeof (long)); + n -= nw * sizeof (long); + do { + *lp++ = 0L; + } while (--nw); + cp = (unsigned char*) lp; + } + ZERO(n, cp); + run &= 7; + } + if (run) + cp[0] &= 0xff >> run; + } else + cp[0] &= ~(_fillmasks[run]>>bx); + x += runs[0]; + } + run = runs[1]; + if (x+run > lastx || run > lastx ) + run = runs[1] = lastx - x; + if (run) { + cp = buf + (x>>3); + bx = x&7; + if (run > 8-bx) { + if (bx) { /* align to byte boundary */ + *cp++ |= 0xff >> bx; + run -= 8-bx; + } + if( (n = run>>3) != 0 ) { /* multiple bytes to fill */ + if ((n/sizeof (long)) > 1) { + /* + * Align to longword boundary and fill. + */ + for (; n && !isAligned(cp, long); n--) + *cp++ = 0xff; + lp = (long*) cp; + nw = (int32)(n / sizeof (long)); + n -= nw * sizeof (long); + do { + *lp++ = -1L; + } while (--nw); + cp = (unsigned char*) lp; + } + FILL(n, cp); + run &= 7; + } + /* Explicit 0xff masking to make icc -check=conversions happy */ + if (run) + cp[0] = (unsigned char)((cp[0] | (0xff00 >> run))&0xff); + } else + cp[0] |= _fillmasks[run]>>bx; + x += runs[1]; + } + } + assert(x == lastx); } #undef ZERO #undef FILL @@ -457,8 +488,8 @@ _TIFFFax3fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx) static int Fax3FixupTags(TIFF* tif) { - (void) tif; - return (1); + (void) tif; + return (1); } /* @@ -471,93 +502,93 @@ Fax3FixupTags(TIFF* tif) static int Fax3SetupState(TIFF* tif) { - static const char module[] = "Fax3SetupState"; - TIFFDirectory* td = &tif->tif_dir; - Fax3BaseState* sp = Fax3State(tif); - int needsRefLine; - Fax3CodecState* dsp = (Fax3CodecState*) Fax3State(tif); - tmsize_t rowbytes; - uint32 rowpixels, nruns; + static const char module[] = "Fax3SetupState"; + TIFFDirectory* td = &tif->tif_dir; + Fax3BaseState* sp = Fax3State(tif); + int needsRefLine; + Fax3CodecState* dsp = (Fax3CodecState*) Fax3State(tif); + tmsize_t rowbytes; + uint32 rowpixels, nruns; - if (td->td_bitspersample != 1) { - TIFFErrorExt(tif->tif_clientdata, module, - "Bits/sample must be 1 for Group 3/4 encoding/decoding"); - return (0); - } - /* - * Calculate the scanline/tile widths. - */ - if (isTiled(tif)) { - rowbytes = TIFFTileRowSize(tif); - rowpixels = td->td_tilewidth; - } else { - rowbytes = TIFFScanlineSize(tif); - rowpixels = td->td_imagewidth; - } - sp->rowbytes = rowbytes; - sp->rowpixels = rowpixels; - /* - * Allocate any additional space required for decoding/encoding. - */ - needsRefLine = ( - (sp->groupoptions & GROUP3OPT_2DENCODING) || - td->td_compression == COMPRESSION_CCITTFAX4 - ); + if (td->td_bitspersample != 1) { + TIFFErrorExt(tif->tif_clientdata, module, + "Bits/sample must be 1 for Group 3/4 encoding/decoding"); + return (0); + } + /* + * Calculate the scanline/tile widths. + */ + if (isTiled(tif)) { + rowbytes = TIFFTileRowSize(tif); + rowpixels = td->td_tilewidth; + } else { + rowbytes = TIFFScanlineSize(tif); + rowpixels = td->td_imagewidth; + } + sp->rowbytes = rowbytes; + sp->rowpixels = rowpixels; + /* + * Allocate any additional space required for decoding/encoding. + */ + needsRefLine = ( + (sp->groupoptions & GROUP3OPT_2DENCODING) || + td->td_compression == COMPRESSION_CCITTFAX4 + ); - /* - Assure that allocation computations do not overflow. + /* + Assure that allocation computations do not overflow. + + TIFFroundup and TIFFSafeMultiply return zero on integer overflow + */ + dsp->runs=(uint32*) NULL; + nruns = TIFFroundup_32(rowpixels,32); + if (needsRefLine) { + nruns = TIFFSafeMultiply(uint32,nruns,2); + } + if ((nruns == 0) || (TIFFSafeMultiply(uint32,nruns,2) == 0)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Row pixels integer overflow (rowpixels %u)", + rowpixels); + return (0); + } + dsp->runs = (uint32*) _TIFFCheckMalloc(tif, + TIFFSafeMultiply(uint32,nruns,2), + sizeof (uint32), + "for Group 3/4 run arrays"); + if (dsp->runs == NULL) + return (0); + memset( dsp->runs, 0, TIFFSafeMultiply(uint32,nruns,2)*sizeof(uint32)); + dsp->curruns = dsp->runs; + if (needsRefLine) + dsp->refruns = dsp->runs + nruns; + else + dsp->refruns = NULL; + if (td->td_compression == COMPRESSION_CCITTFAX3 + && is2DEncoding(dsp)) { /* NB: default is 1D routine */ + tif->tif_decoderow = Fax3Decode2D; + tif->tif_decodestrip = Fax3Decode2D; + tif->tif_decodetile = Fax3Decode2D; + } - TIFFroundup and TIFFSafeMultiply return zero on integer overflow - */ - dsp->runs=(uint32*) NULL; - nruns = TIFFroundup_32(rowpixels,32); - if (needsRefLine) { - nruns = TIFFSafeMultiply(uint32,nruns,2); - } - if ((nruns == 0) || (TIFFSafeMultiply(uint32,nruns,2) == 0)) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "Row pixels integer overflow (rowpixels %u)", - rowpixels); - return (0); - } - dsp->runs = (uint32*) _TIFFCheckMalloc(tif, - TIFFSafeMultiply(uint32,nruns,2), - sizeof (uint32), - "for Group 3/4 run arrays"); - if (dsp->runs == NULL) - return (0); - memset( dsp->runs, 0, TIFFSafeMultiply(uint32,nruns,2)); - dsp->curruns = dsp->runs; - if (needsRefLine) - dsp->refruns = dsp->runs + nruns; - else - dsp->refruns = NULL; - if (td->td_compression == COMPRESSION_CCITTFAX3 - && is2DEncoding(dsp)) { /* NB: default is 1D routine */ - tif->tif_decoderow = Fax3Decode2D; - tif->tif_decodestrip = Fax3Decode2D; - tif->tif_decodetile = Fax3Decode2D; - } + if (needsRefLine) { /* 2d encoding */ + Fax3CodecState* esp = EncoderState(tif); + /* + * 2d encoding requires a scanline + * buffer for the ``reference line''; the + * scanline against which delta encoding + * is referenced. The reference line must + * be initialized to be ``white'' (done elsewhere). + */ + esp->refline = (unsigned char*) _TIFFmalloc(rowbytes); + if (esp->refline == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, + "No space for Group 3/4 reference line"); + return (0); + } + } else /* 1d encoding */ + EncoderState(tif)->refline = NULL; - if (needsRefLine) { /* 2d encoding */ - Fax3CodecState* esp = EncoderState(tif); - /* - * 2d encoding requires a scanline - * buffer for the ``reference line''; the - * scanline against which delta encoding - * is referenced. The reference line must - * be initialized to be ``white'' (done elsewhere). - */ - esp->refline = (unsigned char*) _TIFFmalloc(rowbytes); - if (esp->refline == NULL) { - TIFFErrorExt(tif->tif_clientdata, module, - "No space for Group 3/4 reference line"); - return (0); - } - } else /* 1d encoding */ - EncoderState(tif)->refline = NULL; - - return (1); + return (1); } /* @@ -565,34 +596,34 @@ Fax3SetupState(TIFF* tif) */ #define Fax3FlushBits(tif, sp) { \ - if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \ - (void) TIFFFlushData1(tif); \ - *(tif)->tif_rawcp++ = (uint8) (sp)->data; \ - (tif)->tif_rawcc++; \ - (sp)->data = 0, (sp)->bit = 8; \ + if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \ + (void) TIFFFlushData1(tif); \ + *(tif)->tif_rawcp++ = (uint8) (sp)->data; \ + (tif)->tif_rawcc++; \ + (sp)->data = 0, (sp)->bit = 8; \ } #define _FlushBits(tif) { \ - if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \ - (void) TIFFFlushData1(tif); \ - *(tif)->tif_rawcp++ = (uint8) data; \ - (tif)->tif_rawcc++; \ - data = 0, bit = 8; \ + if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \ + (void) TIFFFlushData1(tif); \ + *(tif)->tif_rawcp++ = (uint8) data; \ + (tif)->tif_rawcc++; \ + data = 0, bit = 8; \ } static const int _msbmask[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; #define _PutBits(tif, bits, length) { \ - while (length > bit) { \ - data |= bits >> (length - bit); \ - length -= bit; \ - _FlushBits(tif); \ - } \ + while (length > bit) { \ + data |= bits >> (length - bit); \ + length -= bit; \ + _FlushBits(tif); \ + } \ assert( length < 9 ); \ - data |= (bits & _msbmask[length]) << (bit - length); \ - bit -= length; \ - if (bit == 0) \ - _FlushBits(tif); \ + data |= (bits & _msbmask[length]) << (bit - length); \ + bit -= length; \ + if (bit == 0) \ + _FlushBits(tif); \ } - + /* * Write a variable-length bit-value to * the output stream. Values are @@ -601,14 +632,14 @@ static const int _msbmask[9] = static void Fax3PutBits(TIFF* tif, unsigned int bits, unsigned int length) { - Fax3CodecState* sp = EncoderState(tif); - unsigned int bit = sp->bit; - int data = sp->data; + Fax3CodecState* sp = EncoderState(tif); + unsigned int bit = sp->bit; + int data = sp->data; - _PutBits(tif, bits, length); + _PutBits(tif, bits, length); - sp->data = data; - sp->bit = bit; + sp->data = data; + sp->bit = bit; } /* @@ -622,7 +653,7 @@ Fax3PutBits(TIFF* tif, unsigned int bits, unsigned int length) int t; \ printf("%08X/%-2d: %s%5d\t", data, bit, DEBUG_COLOR(what), len); \ for (t = length-1; t >= 0; t--) \ - putchar(code & (1<bit; - int data = sp->data; - unsigned int code, length; + Fax3CodecState* sp = EncoderState(tif); + unsigned int bit = sp->bit; + int data = sp->data; + unsigned int code, length; - while (span >= 2624) { - const tableentry* te = &tab[63 + (2560>>6)]; - code = te->code, length = te->length; + while (span >= 2624) { + const tableentry* te = &tab[63 + (2560>>6)]; + code = te->code; + length = te->length; #ifdef FAX3_DEBUG - DEBUG_PRINT("MakeUp", te->runlen); + DEBUG_PRINT("MakeUp", te->runlen); #endif - _PutBits(tif, code, length); - span -= te->runlen; - } - if (span >= 64) { - const tableentry* te = &tab[63 + (span>>6)]; - assert(te->runlen == 64*(span>>6)); - code = te->code, length = te->length; + _PutBits(tif, code, length); + span -= te->runlen; + } + if (span >= 64) { + const tableentry* te = &tab[63 + (span>>6)]; + assert(te->runlen == 64*(span>>6)); + code = te->code; + length = te->length; #ifdef FAX3_DEBUG - DEBUG_PRINT("MakeUp", te->runlen); + DEBUG_PRINT("MakeUp", te->runlen); #endif - _PutBits(tif, code, length); - span -= te->runlen; - } - code = tab[span].code, length = tab[span].length; + _PutBits(tif, code, length); + span -= te->runlen; + } + code = tab[span].code; + length = tab[span].length; #ifdef FAX3_DEBUG - DEBUG_PRINT(" Term", tab[span].runlen); + DEBUG_PRINT(" Term", tab[span].runlen); #endif - _PutBits(tif, code, length); + _PutBits(tif, code, length); - sp->data = data; - sp->bit = bit; + sp->data = data; + sp->bit = bit; } /* @@ -679,35 +713,37 @@ putspan(TIFF* tif, int32 span, const tableentry* tab) static void Fax3PutEOL(TIFF* tif) { - Fax3CodecState* sp = EncoderState(tif); - unsigned int bit = sp->bit; - int data = sp->data; - unsigned int code, length, tparm; + Fax3CodecState* sp = EncoderState(tif); + unsigned int bit = sp->bit; + int data = sp->data; + unsigned int code, length, tparm; - if (sp->b.groupoptions & GROUP3OPT_FILLBITS) { - /* - * Force bit alignment so EOL will terminate on - * a byte boundary. That is, force the bit alignment - * to 16-12 = 4 before putting out the EOL code. - */ - int align = 8 - 4; - if (align != sp->bit) { - if (align > sp->bit) - align = sp->bit + (8 - align); - else - align = sp->bit - align; - code = 0; - tparm=align; - _PutBits(tif, 0, tparm); - } - } - code = EOL, length = 12; - if (is2DEncoding(sp)) - code = (code<<1) | (sp->tag == G3_1D), length++; - _PutBits(tif, code, length); + if (sp->b.groupoptions & GROUP3OPT_FILLBITS) { + /* + * Force bit alignment so EOL will terminate on + * a byte boundary. That is, force the bit alignment + * to 16-12 = 4 before putting out the EOL code. + */ + int align = 8 - 4; + if (align != sp->bit) { + if (align > sp->bit) + align = sp->bit + (8 - align); + else + align = sp->bit - align; + tparm=align; + _PutBits(tif, 0, tparm); + } + } + code = EOL; + length = 12; + if (is2DEncoding(sp)) { + code = (code<<1) | (sp->tag == G3_1D); + length++; + } + _PutBits(tif, code, length); - sp->data = data; - sp->bit = bit; + sp->data = data; + sp->bit = bit; } /* @@ -716,40 +752,40 @@ Fax3PutEOL(TIFF* tif) static int Fax3PreEncode(TIFF* tif, uint16 s) { - Fax3CodecState* sp = EncoderState(tif); + Fax3CodecState* sp = EncoderState(tif); - (void) s; - assert(sp != NULL); - sp->bit = 8; - sp->data = 0; - sp->tag = G3_1D; - /* - * This is necessary for Group 4; otherwise it isn't - * needed because the first scanline of each strip ends - * up being copied into the refline. - */ - if (sp->refline) - _TIFFmemset(sp->refline, 0x00, sp->b.rowbytes); - if (is2DEncoding(sp)) { - float res = tif->tif_dir.td_yresolution; - /* - * The CCITT spec says that when doing 2d encoding, you - * should only do it on K consecutive scanlines, where K - * depends on the resolution of the image being encoded - * (2 for <= 200 lpi, 4 for > 200 lpi). Since the directory - * code initializes td_yresolution to 0, this code will - * select a K of 2 unless the YResolution tag is set - * appropriately. (Note also that we fudge a little here - * and use 150 lpi to avoid problems with units conversion.) - */ - if (tif->tif_dir.td_resolutionunit == RESUNIT_CENTIMETER) - res *= 2.54f; /* convert to inches */ - sp->maxk = (res > 150 ? 4 : 2); - sp->k = sp->maxk-1; - } else - sp->k = sp->maxk = 0; - sp->line = 0; - return (1); + (void) s; + assert(sp != NULL); + sp->bit = 8; + sp->data = 0; + sp->tag = G3_1D; + /* + * This is necessary for Group 4; otherwise it isn't + * needed because the first scanline of each strip ends + * up being copied into the refline. + */ + if (sp->refline) + _TIFFmemset(sp->refline, 0x00, sp->b.rowbytes); + if (is2DEncoding(sp)) { + float res = tif->tif_dir.td_yresolution; + /* + * The CCITT spec says that when doing 2d encoding, you + * should only do it on K consecutive scanlines, where K + * depends on the resolution of the image being encoded + * (2 for <= 200 lpi, 4 for > 200 lpi). Since the directory + * code initializes td_yresolution to 0, this code will + * select a K of 2 unless the YResolution tag is set + * appropriately. (Note also that we fudge a little here + * and use 150 lpi to avoid problems with units conversion.) + */ + if (tif->tif_dir.td_resolutionunit == RESUNIT_CENTIMETER) + res *= 2.54f; /* convert to inches */ + sp->maxk = (res > 150 ? 4 : 2); + sp->k = sp->maxk-1; + } else + sp->k = sp->maxk = 0; + sp->line = 0; + return (1); } static const unsigned char zeroruns[256] = { @@ -804,122 +840,128 @@ static int32 find1span(unsigned char*, int32, int32); * table. The ``base'' of the bit string is supplied * along with the start+end bit indices. */ -static int32 +inline static int32 find0span(unsigned char* bp, int32 bs, int32 be) { - int32 bits = be - bs; - int32 n, span; + int32 bits = be - bs; + int32 n, span; - bp += bs>>3; - /* - * Check partial byte on lhs. - */ - if (bits > 0 && (n = (bs & 7))) { - span = zeroruns[(*bp << n) & 0xff]; - if (span > 8-n) /* table value too generous */ - span = 8-n; - if (span > bits) /* constrain span to bit range */ - span = bits; - if (n+span < 8) /* doesn't extend to edge of byte */ - return (span); - bits -= span; - bp++; - } else - span = 0; - if (bits >= (int32)(2 * 8 * sizeof(long))) { - long* lp; - /* - * Align to longword boundary and check longwords. - */ - while (!isAligned(bp, long)) { - if (*bp != 0x00) - return (span + zeroruns[*bp]); - span += 8, bits -= 8; - bp++; - } - lp = (long*) bp; - while ((bits >= (int32)(8 * sizeof(long))) && (0 == *lp)) { - span += 8*sizeof (long), bits -= 8*sizeof (long); - lp++; - } - bp = (unsigned char*) lp; - } - /* - * Scan full bytes for all 0's. - */ - while (bits >= 8) { - if (*bp != 0x00) /* end of run */ - return (span + zeroruns[*bp]); - span += 8, bits -= 8; - bp++; - } - /* - * Check partial byte on rhs. - */ - if (bits > 0) { - n = zeroruns[*bp]; - span += (n > bits ? bits : n); - } - return (span); + bp += bs>>3; + /* + * Check partial byte on lhs. + */ + if (bits > 0 && (n = (bs & 7)) != 0) { + span = zeroruns[(*bp << n) & 0xff]; + if (span > 8-n) /* table value too generous */ + span = 8-n; + if (span > bits) /* constrain span to bit range */ + span = bits; + if (n+span < 8) /* doesn't extend to edge of byte */ + return (span); + bits -= span; + bp++; + } else + span = 0; + if (bits >= (int32)(2 * 8 * sizeof(long))) { + long* lp; + /* + * Align to longword boundary and check longwords. + */ + while (!isAligned(bp, long)) { + if (*bp != 0x00) + return (span + zeroruns[*bp]); + span += 8; + bits -= 8; + bp++; + } + lp = (long*) bp; + while ((bits >= (int32)(8 * sizeof(long))) && (0 == *lp)) { + span += 8*sizeof (long); + bits -= 8*sizeof (long); + lp++; + } + bp = (unsigned char*) lp; + } + /* + * Scan full bytes for all 0's. + */ + while (bits >= 8) { + if (*bp != 0x00) /* end of run */ + return (span + zeroruns[*bp]); + span += 8; + bits -= 8; + bp++; + } + /* + * Check partial byte on rhs. + */ + if (bits > 0) { + n = zeroruns[*bp]; + span += (n > bits ? bits : n); + } + return (span); } -static int32 +inline static int32 find1span(unsigned char* bp, int32 bs, int32 be) { - int32 bits = be - bs; - int32 n, span; + int32 bits = be - bs; + int32 n, span; - bp += bs>>3; - /* - * Check partial byte on lhs. - */ - if (bits > 0 && (n = (bs & 7))) { - span = oneruns[(*bp << n) & 0xff]; - if (span > 8-n) /* table value too generous */ - span = 8-n; - if (span > bits) /* constrain span to bit range */ - span = bits; - if (n+span < 8) /* doesn't extend to edge of byte */ - return (span); - bits -= span; - bp++; - } else - span = 0; - if (bits >= (int32)(2 * 8 * sizeof(long))) { - long* lp; - /* - * Align to longword boundary and check longwords. - */ - while (!isAligned(bp, long)) { - if (*bp != 0xff) - return (span + oneruns[*bp]); - span += 8, bits -= 8; - bp++; - } - lp = (long*) bp; - while ((bits >= (int32)(8 * sizeof(long))) && (~0 == *lp)) { - span += 8*sizeof (long), bits -= 8*sizeof (long); - lp++; - } - bp = (unsigned char*) lp; - } - /* - * Scan full bytes for all 1's. - */ - while (bits >= 8) { - if (*bp != 0xff) /* end of run */ - return (span + oneruns[*bp]); - span += 8, bits -= 8; - bp++; - } - /* - * Check partial byte on rhs. - */ - if (bits > 0) { - n = oneruns[*bp]; - span += (n > bits ? bits : n); - } - return (span); + bp += bs>>3; + /* + * Check partial byte on lhs. + */ + if (bits > 0 && (n = (bs & 7)) != 0) { + span = oneruns[(*bp << n) & 0xff]; + if (span > 8-n) /* table value too generous */ + span = 8-n; + if (span > bits) /* constrain span to bit range */ + span = bits; + if (n+span < 8) /* doesn't extend to edge of byte */ + return (span); + bits -= span; + bp++; + } else + span = 0; + if (bits >= (int32)(2 * 8 * sizeof(long))) { + long* lp; + /* + * Align to longword boundary and check longwords. + */ + while (!isAligned(bp, long)) { + if (*bp != 0xff) + return (span + oneruns[*bp]); + span += 8; + bits -= 8; + bp++; + } + lp = (long*) bp; + while ((bits >= (int32)(8 * sizeof(long))) && (~0 == *lp)) { + span += 8*sizeof (long); + bits -= 8*sizeof (long); + lp++; + } + bp = (unsigned char*) lp; + } + /* + * Scan full bytes for all 1's. + */ + while (bits >= 8) { + if (*bp != 0xff) /* end of run */ + return (span + oneruns[*bp]); + span += 8; + bits -= 8; + bp++; + } + /* + * Check partial byte on rhs. + */ + if (bits > 0) { + n = oneruns[*bp]; + span += (n > bits ? bits : n); + } + return (span); } /* @@ -929,13 +971,13 @@ find1span(unsigned char* bp, int32 bs, int32 be) * exists. */ #define finddiff(_cp, _bs, _be, _color) \ - (_bs + (_color ? find1span(_cp,_bs,_be) : find0span(_cp,_bs,_be))) + (_bs + (_color ? find1span(_cp,_bs,_be) : find0span(_cp,_bs,_be))) /* * Like finddiff, but also check the starting bit * against the end in case start > end. */ #define finddiff2(_cp, _bs, _be, _color) \ - (_bs < _be ? finddiff(_cp,_bs,_be,_color) : _be) + (_bs < _be ? finddiff(_cp,_bs,_be,_color) : _be) /* * 1d-encode a row of pixels. The encoding is @@ -945,30 +987,30 @@ find1span(unsigned char* bp, int32 bs, int32 be) static int Fax3Encode1DRow(TIFF* tif, unsigned char* bp, uint32 bits) { - Fax3CodecState* sp = EncoderState(tif); - int32 span; + Fax3CodecState* sp = EncoderState(tif); + int32 span; uint32 bs = 0; - for (;;) { - span = find0span(bp, bs, bits); /* white span */ - putspan(tif, span, TIFFFaxWhiteCodes); - bs += span; - if (bs >= bits) - break; - span = find1span(bp, bs, bits); /* black span */ - putspan(tif, span, TIFFFaxBlackCodes); - bs += span; - if (bs >= bits) - break; - } - if (sp->b.mode & (FAXMODE_BYTEALIGN|FAXMODE_WORDALIGN)) { - if (sp->bit != 8) /* byte-align */ - Fax3FlushBits(tif, sp); - if ((sp->b.mode&FAXMODE_WORDALIGN) && - !isAligned(tif->tif_rawcp, uint16)) - Fax3FlushBits(tif, sp); - } - return (1); + for (;;) { + span = find0span(bp, bs, bits); /* white span */ + putspan(tif, span, TIFFFaxWhiteCodes); + bs += span; + if (bs >= bits) + break; + span = find1span(bp, bs, bits); /* black span */ + putspan(tif, span, TIFFFaxBlackCodes); + bs += span; + if (bs >= bits) + break; + } + if (sp->b.mode & (FAXMODE_BYTEALIGN|FAXMODE_WORDALIGN)) { + if (sp->bit != 8) /* byte-align */ + Fax3FlushBits(tif, sp); + if ((sp->b.mode&FAXMODE_WORDALIGN) && + !isAligned(tif->tif_rawcp, uint16)) + Fax3FlushBits(tif, sp); + } + return (1); } static const tableentry horizcode = @@ -994,40 +1036,44 @@ Fax3Encode2DRow(TIFF* tif, unsigned char* bp, unsigned char* rp, uint32 bits) { #define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1) uint32 a0 = 0; - uint32 a1 = (PIXEL(bp, 0) != 0 ? 0 : finddiff(bp, 0, bits, 0)); - uint32 b1 = (PIXEL(rp, 0) != 0 ? 0 : finddiff(rp, 0, bits, 0)); - uint32 a2, b2; + uint32 a1 = (PIXEL(bp, 0) != 0 ? 0 : finddiff(bp, 0, bits, 0)); + uint32 b1 = (PIXEL(rp, 0) != 0 ? 0 : finddiff(rp, 0, bits, 0)); + uint32 a2, b2; - for (;;) { - b2 = finddiff2(rp, b1, bits, PIXEL(rp,b1)); - if (b2 >= a1) { - int32 d = b1 - a1; - if (!(-3 <= d && d <= 3)) { /* horizontal mode */ - a2 = finddiff2(bp, a1, bits, PIXEL(bp,a1)); - putcode(tif, &horizcode); - if (a0+a1 == 0 || PIXEL(bp, a0) == 0) { - putspan(tif, a1-a0, TIFFFaxWhiteCodes); - putspan(tif, a2-a1, TIFFFaxBlackCodes); - } else { - putspan(tif, a1-a0, TIFFFaxBlackCodes); - putspan(tif, a2-a1, TIFFFaxWhiteCodes); - } - a0 = a2; - } else { /* vertical mode */ - putcode(tif, &vcodes[d+3]); - a0 = a1; - } - } else { /* pass mode */ - putcode(tif, &passcode); - a0 = b2; - } - if (a0 >= bits) - break; - a1 = finddiff(bp, a0, bits, PIXEL(bp,a0)); - b1 = finddiff(rp, a0, bits, !PIXEL(bp,a0)); - b1 = finddiff(rp, b1, bits, PIXEL(bp,a0)); - } - return (1); + for (;;) { + b2 = finddiff2(rp, b1, bits, PIXEL(rp,b1)); + if (b2 >= a1) { + /* Naive computation triggers -fsanitize=undefined,unsigned-integer-overflow */ + /* although it is correct unless the difference between both is < 31 bit */ + /* int32 d = b1 - a1; */ + int32 d = (b1 >= a1 && b1 - a1 <= 3U) ? (int32)(b1 - a1): + (b1 < a1 && a1 - b1 <= 3U) ? -(int32)(a1 - b1) : 0x7FFFFFFF; + if (!(-3 <= d && d <= 3)) { /* horizontal mode */ + a2 = finddiff2(bp, a1, bits, PIXEL(bp,a1)); + putcode(tif, &horizcode); + if (a0+a1 == 0 || PIXEL(bp, a0) == 0) { + putspan(tif, a1-a0, TIFFFaxWhiteCodes); + putspan(tif, a2-a1, TIFFFaxBlackCodes); + } else { + putspan(tif, a1-a0, TIFFFaxBlackCodes); + putspan(tif, a2-a1, TIFFFaxWhiteCodes); + } + a0 = a2; + } else { /* vertical mode */ + putcode(tif, &vcodes[d+3]); + a0 = a1; + } + } else { /* pass mode */ + putcode(tif, &passcode); + a0 = b2; + } + if (a0 >= bits) + break; + a1 = finddiff(bp, a0, bits, PIXEL(bp,a0)); + b1 = finddiff(rp, a0, bits, !PIXEL(bp,a0)); + b1 = finddiff(rp, b1, bits, PIXEL(bp,a0)); + } + return (1); #undef PIXEL } @@ -1037,90 +1083,92 @@ Fax3Encode2DRow(TIFF* tif, unsigned char* bp, unsigned char* rp, uint32 bits) static int Fax3Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - static const char module[] = "Fax3Encode"; - Fax3CodecState* sp = EncoderState(tif); - (void) s; - if (cc % sp->b.rowbytes) - { - TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be written"); - return (0); - } - while (cc > 0) { - if ((sp->b.mode & FAXMODE_NOEOL) == 0) - Fax3PutEOL(tif); - if (is2DEncoding(sp)) { - if (sp->tag == G3_1D) { - if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) - return (0); - sp->tag = G3_2D; - } else { - if (!Fax3Encode2DRow(tif, bp, sp->refline, - sp->b.rowpixels)) - return (0); - sp->k--; - } - if (sp->k == 0) { - sp->tag = G3_1D; - sp->k = sp->maxk-1; - } else - _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes); - } else { - if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) - return (0); - } - bp += sp->b.rowbytes; - cc -= sp->b.rowbytes; - } - return (1); + static const char module[] = "Fax3Encode"; + Fax3CodecState* sp = EncoderState(tif); + (void) s; + if (cc % sp->b.rowbytes) + { + TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be written"); + return (0); + } + while (cc > 0) { + if ((sp->b.mode & FAXMODE_NOEOL) == 0) + Fax3PutEOL(tif); + if (is2DEncoding(sp)) { + if (sp->tag == G3_1D) { + if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) + return (0); + sp->tag = G3_2D; + } else { + if (!Fax3Encode2DRow(tif, bp, sp->refline, + sp->b.rowpixels)) + return (0); + sp->k--; + } + if (sp->k == 0) { + sp->tag = G3_1D; + sp->k = sp->maxk-1; + } else + _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes); + } else { + if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels)) + return (0); + } + bp += sp->b.rowbytes; + cc -= sp->b.rowbytes; + } + return (1); } static int Fax3PostEncode(TIFF* tif) { - Fax3CodecState* sp = EncoderState(tif); + Fax3CodecState* sp = EncoderState(tif); - if (sp->bit != 8) - Fax3FlushBits(tif, sp); - return (1); + if (sp->bit != 8) + Fax3FlushBits(tif, sp); + return (1); } static void Fax3Close(TIFF* tif) { - if ((Fax3State(tif)->mode & FAXMODE_NORTC) == 0) { - Fax3CodecState* sp = EncoderState(tif); - unsigned int code = EOL; - unsigned int length = 12; - int i; + if ((Fax3State(tif)->mode & FAXMODE_NORTC) == 0 && tif->tif_rawcp) { + Fax3CodecState* sp = EncoderState(tif); + unsigned int code = EOL; + unsigned int length = 12; + int i; - if (is2DEncoding(sp)) - code = (code<<1) | (sp->tag == G3_1D), length++; - for (i = 0; i < 6; i++) - Fax3PutBits(tif, code, length); - Fax3FlushBits(tif, sp); - } + if (is2DEncoding(sp)) { + code = (code<<1) | (sp->tag == G3_1D); + length++; + } + for (i = 0; i < 6; i++) + Fax3PutBits(tif, code, length); + Fax3FlushBits(tif, sp); + } } static void Fax3Cleanup(TIFF* tif) { - Fax3CodecState* sp = DecoderState(tif); + Fax3CodecState* sp = DecoderState(tif); + + assert(sp != 0); - assert(sp != 0); + tif->tif_tagmethods.vgetfield = sp->b.vgetparent; + tif->tif_tagmethods.vsetfield = sp->b.vsetparent; + tif->tif_tagmethods.printdir = sp->b.printdir; - tif->tif_tagmethods.vgetfield = sp->b.vgetparent; - tif->tif_tagmethods.vsetfield = sp->b.vsetparent; - tif->tif_tagmethods.printdir = sp->b.printdir; + if (sp->runs) + _TIFFfree(sp->runs); + if (sp->refline) + _TIFFfree(sp->refline); - if (sp->runs) - _TIFFfree(sp->runs); - if (sp->refline) - _TIFFfree(sp->refline); + _TIFFfree(tif->tif_data); + tif->tif_data = NULL; - _TIFFfree(tif->tif_data); - tif->tif_data = NULL; - - _TIFFSetDefaultCompressionState(tif); + _TIFFSetDefaultCompressionState(tif); } #define FIELD_BADFAXLINES (FIELD_CODEC+0) @@ -1145,227 +1193,232 @@ static const TIFFField fax4Fields[] = { static int Fax3VSetField(TIFF* tif, uint32 tag, va_list ap) { - Fax3BaseState* sp = Fax3State(tif); - const TIFFField* fip; + Fax3BaseState* sp = Fax3State(tif); + const TIFFField* fip; - assert(sp != 0); - assert(sp->vsetparent != 0); + assert(sp != 0); + assert(sp->vsetparent != 0); - switch (tag) { - case TIFFTAG_FAXMODE: - sp->mode = (int) va_arg(ap, int); - return 1; /* NB: pseudo tag */ - case TIFFTAG_FAXFILLFUNC: - DecoderState(tif)->fill = va_arg(ap, TIFFFaxFillFunc); - return 1; /* NB: pseudo tag */ - case TIFFTAG_GROUP3OPTIONS: - /* XXX: avoid reading options if compression mismatches. */ - if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX3) - sp->groupoptions = (uint32) va_arg(ap, uint32); - break; - case TIFFTAG_GROUP4OPTIONS: - /* XXX: avoid reading options if compression mismatches. */ - if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4) - sp->groupoptions = (uint32) va_arg(ap, uint32); - break; - case TIFFTAG_BADFAXLINES: - sp->badfaxlines = (uint32) va_arg(ap, uint32); - break; - case TIFFTAG_CLEANFAXDATA: - sp->cleanfaxdata = (uint16) va_arg(ap, uint16_vap); - break; - case TIFFTAG_CONSECUTIVEBADFAXLINES: - sp->badfaxrun = (uint32) va_arg(ap, uint32); - break; - default: - return (*sp->vsetparent)(tif, tag, ap); - } + switch (tag) { + case TIFFTAG_FAXMODE: + sp->mode = (int) va_arg(ap, int); + return 1; /* NB: pseudo tag */ + case TIFFTAG_FAXFILLFUNC: + DecoderState(tif)->fill = va_arg(ap, TIFFFaxFillFunc); + return 1; /* NB: pseudo tag */ + case TIFFTAG_GROUP3OPTIONS: + /* XXX: avoid reading options if compression mismatches. */ + if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX3) + sp->groupoptions = (uint32) va_arg(ap, uint32); + break; + case TIFFTAG_GROUP4OPTIONS: + /* XXX: avoid reading options if compression mismatches. */ + if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4) + sp->groupoptions = (uint32) va_arg(ap, uint32); + break; + case TIFFTAG_BADFAXLINES: + sp->badfaxlines = (uint32) va_arg(ap, uint32); + break; + case TIFFTAG_CLEANFAXDATA: + sp->cleanfaxdata = (uint16) va_arg(ap, uint16_vap); + break; + case TIFFTAG_CONSECUTIVEBADFAXLINES: + sp->badfaxrun = (uint32) va_arg(ap, uint32); + break; + default: + return (*sp->vsetparent)(tif, tag, ap); + } + + if ((fip = TIFFFieldWithTag(tif, tag)) != NULL) + TIFFSetFieldBit(tif, fip->field_bit); + else + return 0; - if ((fip = TIFFFieldWithTag(tif, tag))) - TIFFSetFieldBit(tif, fip->field_bit); - else - return 0; - - tif->tif_flags |= TIFF_DIRTYDIRECT; - return 1; + tif->tif_flags |= TIFF_DIRTYDIRECT; + return 1; } static int Fax3VGetField(TIFF* tif, uint32 tag, va_list ap) { - Fax3BaseState* sp = Fax3State(tif); + Fax3BaseState* sp = Fax3State(tif); - assert(sp != 0); + assert(sp != 0); - switch (tag) { - case TIFFTAG_FAXMODE: - *va_arg(ap, int*) = sp->mode; - break; - case TIFFTAG_FAXFILLFUNC: - *va_arg(ap, TIFFFaxFillFunc*) = DecoderState(tif)->fill; - break; - case TIFFTAG_GROUP3OPTIONS: - case TIFFTAG_GROUP4OPTIONS: - *va_arg(ap, uint32*) = sp->groupoptions; - break; - case TIFFTAG_BADFAXLINES: - *va_arg(ap, uint32*) = sp->badfaxlines; - break; - case TIFFTAG_CLEANFAXDATA: - *va_arg(ap, uint16*) = sp->cleanfaxdata; - break; - case TIFFTAG_CONSECUTIVEBADFAXLINES: - *va_arg(ap, uint32*) = sp->badfaxrun; - break; - default: - return (*sp->vgetparent)(tif, tag, ap); - } - return (1); + switch (tag) { + case TIFFTAG_FAXMODE: + *va_arg(ap, int*) = sp->mode; + break; + case TIFFTAG_FAXFILLFUNC: + *va_arg(ap, TIFFFaxFillFunc*) = DecoderState(tif)->fill; + break; + case TIFFTAG_GROUP3OPTIONS: + case TIFFTAG_GROUP4OPTIONS: + *va_arg(ap, uint32*) = sp->groupoptions; + break; + case TIFFTAG_BADFAXLINES: + *va_arg(ap, uint32*) = sp->badfaxlines; + break; + case TIFFTAG_CLEANFAXDATA: + *va_arg(ap, uint16*) = sp->cleanfaxdata; + break; + case TIFFTAG_CONSECUTIVEBADFAXLINES: + *va_arg(ap, uint32*) = sp->badfaxrun; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); } static void Fax3PrintDir(TIFF* tif, FILE* fd, long flags) { - Fax3BaseState* sp = Fax3State(tif); + Fax3BaseState* sp = Fax3State(tif); - assert(sp != 0); + assert(sp != 0); - (void) flags; - if (TIFFFieldSet(tif,FIELD_OPTIONS)) { - const char* sep = " "; - if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4) { - fprintf(fd, " Group 4 Options:"); - if (sp->groupoptions & GROUP4OPT_UNCOMPRESSED) - fprintf(fd, "%suncompressed data", sep); - } else { + (void) flags; + if (TIFFFieldSet(tif,FIELD_OPTIONS)) { + const char* sep = " "; + if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4) { + fprintf(fd, " Group 4 Options:"); + if (sp->groupoptions & GROUP4OPT_UNCOMPRESSED) + fprintf(fd, "%suncompressed data", sep); + } else { - fprintf(fd, " Group 3 Options:"); - if (sp->groupoptions & GROUP3OPT_2DENCODING) - fprintf(fd, "%s2-d encoding", sep), sep = "+"; - if (sp->groupoptions & GROUP3OPT_FILLBITS) - fprintf(fd, "%sEOL padding", sep), sep = "+"; - if (sp->groupoptions & GROUP3OPT_UNCOMPRESSED) - fprintf(fd, "%suncompressed data", sep); - } - fprintf(fd, " (%lu = 0x%lx)\n", + fprintf(fd, " Group 3 Options:"); + if (sp->groupoptions & GROUP3OPT_2DENCODING) { + fprintf(fd, "%s2-d encoding", sep); + sep = "+"; + } + if (sp->groupoptions & GROUP3OPT_FILLBITS) { + fprintf(fd, "%sEOL padding", sep); + sep = "+"; + } + if (sp->groupoptions & GROUP3OPT_UNCOMPRESSED) + fprintf(fd, "%suncompressed data", sep); + } + fprintf(fd, " (%lu = 0x%lx)\n", (unsigned long) sp->groupoptions, (unsigned long) sp->groupoptions); - } - if (TIFFFieldSet(tif,FIELD_CLEANFAXDATA)) { - fprintf(fd, " Fax Data:"); - switch (sp->cleanfaxdata) { - case CLEANFAXDATA_CLEAN: - fprintf(fd, " clean"); - break; - case CLEANFAXDATA_REGENERATED: - fprintf(fd, " receiver regenerated"); - break; - case CLEANFAXDATA_UNCLEAN: - fprintf(fd, " uncorrected errors"); - break; - } - fprintf(fd, " (%u = 0x%x)\n", - sp->cleanfaxdata, sp->cleanfaxdata); - } - if (TIFFFieldSet(tif,FIELD_BADFAXLINES)) - fprintf(fd, " Bad Fax Lines: %lu\n", + } + if (TIFFFieldSet(tif,FIELD_CLEANFAXDATA)) { + fprintf(fd, " Fax Data:"); + switch (sp->cleanfaxdata) { + case CLEANFAXDATA_CLEAN: + fprintf(fd, " clean"); + break; + case CLEANFAXDATA_REGENERATED: + fprintf(fd, " receiver regenerated"); + break; + case CLEANFAXDATA_UNCLEAN: + fprintf(fd, " uncorrected errors"); + break; + } + fprintf(fd, " (%u = 0x%x)\n", + sp->cleanfaxdata, sp->cleanfaxdata); + } + if (TIFFFieldSet(tif,FIELD_BADFAXLINES)) + fprintf(fd, " Bad Fax Lines: %lu\n", (unsigned long) sp->badfaxlines); - if (TIFFFieldSet(tif,FIELD_BADFAXRUN)) - fprintf(fd, " Consecutive Bad Fax Lines: %lu\n", - (unsigned long) sp->badfaxrun); - if (sp->printdir) - (*sp->printdir)(tif, fd, flags); + if (TIFFFieldSet(tif,FIELD_BADFAXRUN)) + fprintf(fd, " Consecutive Bad Fax Lines: %lu\n", + (unsigned long) sp->badfaxrun); + if (sp->printdir) + (*sp->printdir)(tif, fd, flags); } static int InitCCITTFax3(TIFF* tif) { - static const char module[] = "InitCCITTFax3"; - Fax3BaseState* sp; + static const char module[] = "InitCCITTFax3"; + Fax3BaseState* sp; - /* - * Merge codec-specific tag information. - */ - if (!_TIFFMergeFields(tif, faxFields, TIFFArrayCount(faxFields))) { - TIFFErrorExt(tif->tif_clientdata, "InitCCITTFax3", - "Merging common CCITT Fax codec-specific tags failed"); - return 0; - } + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, faxFields, TIFFArrayCount(faxFields))) { + TIFFErrorExt(tif->tif_clientdata, "InitCCITTFax3", + "Merging common CCITT Fax codec-specific tags failed"); + return 0; + } - /* - * Allocate state block so tag methods have storage to record values. - */ - tif->tif_data = (uint8*) - _TIFFmalloc(sizeof (Fax3CodecState)); + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (uint8*) + _TIFFmalloc(sizeof (Fax3CodecState)); - if (tif->tif_data == NULL) { - TIFFErrorExt(tif->tif_clientdata, module, - "No space for state block"); - return (0); - } + if (tif->tif_data == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, + "No space for state block"); + return (0); + } + _TIFFmemset(tif->tif_data, 0, sizeof (Fax3CodecState)); - sp = Fax3State(tif); + sp = Fax3State(tif); sp->rw_mode = tif->tif_mode; - /* - * Override parent get/set field methods. - */ - sp->vgetparent = tif->tif_tagmethods.vgetfield; - tif->tif_tagmethods.vgetfield = Fax3VGetField; /* hook for codec tags */ - sp->vsetparent = tif->tif_tagmethods.vsetfield; - tif->tif_tagmethods.vsetfield = Fax3VSetField; /* hook for codec tags */ - sp->printdir = tif->tif_tagmethods.printdir; - tif->tif_tagmethods.printdir = Fax3PrintDir; /* hook for codec tags */ - sp->groupoptions = 0; + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = Fax3VGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = Fax3VSetField; /* hook for codec tags */ + sp->printdir = tif->tif_tagmethods.printdir; + tif->tif_tagmethods.printdir = Fax3PrintDir; /* hook for codec tags */ + sp->groupoptions = 0; - if (sp->rw_mode == O_RDONLY) /* FIXME: improve for in place update */ - tif->tif_flags |= TIFF_NOBITREV; /* decoder does bit reversal */ - DecoderState(tif)->runs = NULL; - TIFFSetField(tif, TIFFTAG_FAXFILLFUNC, _TIFFFax3fillruns); - EncoderState(tif)->refline = NULL; + if (sp->rw_mode == O_RDONLY) /* FIXME: improve for in place update */ + tif->tif_flags |= TIFF_NOBITREV; /* decoder does bit reversal */ + DecoderState(tif)->runs = NULL; + TIFFSetField(tif, TIFFTAG_FAXFILLFUNC, _TIFFFax3fillruns); + EncoderState(tif)->refline = NULL; - /* - * Install codec methods. - */ - tif->tif_fixuptags = Fax3FixupTags; - tif->tif_setupdecode = Fax3SetupState; - tif->tif_predecode = Fax3PreDecode; - tif->tif_decoderow = Fax3Decode1D; - tif->tif_decodestrip = Fax3Decode1D; - tif->tif_decodetile = Fax3Decode1D; - tif->tif_setupencode = Fax3SetupState; - tif->tif_preencode = Fax3PreEncode; - tif->tif_postencode = Fax3PostEncode; - tif->tif_encoderow = Fax3Encode; - tif->tif_encodestrip = Fax3Encode; - tif->tif_encodetile = Fax3Encode; - tif->tif_close = Fax3Close; - tif->tif_cleanup = Fax3Cleanup; + /* + * Install codec methods. + */ + tif->tif_fixuptags = Fax3FixupTags; + tif->tif_setupdecode = Fax3SetupState; + tif->tif_predecode = Fax3PreDecode; + tif->tif_decoderow = Fax3Decode1D; + tif->tif_decodestrip = Fax3Decode1D; + tif->tif_decodetile = Fax3Decode1D; + tif->tif_setupencode = Fax3SetupState; + tif->tif_preencode = Fax3PreEncode; + tif->tif_postencode = Fax3PostEncode; + tif->tif_encoderow = Fax3Encode; + tif->tif_encodestrip = Fax3Encode; + tif->tif_encodetile = Fax3Encode; + tif->tif_close = Fax3Close; + tif->tif_cleanup = Fax3Cleanup; - return (1); + return (1); } int TIFFInitCCITTFax3(TIFF* tif, int scheme) { - (void) scheme; - if (InitCCITTFax3(tif)) { - /* - * Merge codec-specific tag information. - */ - if (!_TIFFMergeFields(tif, fax3Fields, - TIFFArrayCount(fax3Fields))) { - TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax3", - "Merging CCITT Fax 3 codec-specific tags failed"); - return 0; - } + (void) scheme; + if (InitCCITTFax3(tif)) { + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, fax3Fields, + TIFFArrayCount(fax3Fields))) { + TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax3", + "Merging CCITT Fax 3 codec-specific tags failed"); + return 0; + } - /* - * The default format is Class/F-style w/o RTC. - */ - return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_CLASSF); - } else - return 01; + /* + * The default format is Class/F-style w/o RTC. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_CLASSF); + } else + return 01; } /* @@ -1380,49 +1433,49 @@ TIFFInitCCITTFax3(TIFF* tif, int scheme) static int Fax4Decode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) { - DECLARE_STATE_2D(tif, sp, "Fax4Decode"); - (void) s; - if (occ % sp->b.rowbytes) - { - TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); - return (-1); - } - CACHE_STATE(tif, sp); - while (occ > 0) { - a0 = 0; - RunLength = 0; - pa = thisrun = sp->curruns; - pb = sp->refruns; - b1 = *pb++; + DECLARE_STATE_2D(tif, sp, "Fax4Decode"); + (void) s; + if (occ % sp->b.rowbytes) + { + TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); + return (-1); + } + CACHE_STATE(tif, sp); + while (occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun = sp->curruns; + pb = sp->refruns; + b1 = *pb++; #ifdef FAX3_DEBUG - printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); - printf("-------------------- %d\n", tif->tif_row); - fflush(stdout); + printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", tif->tif_row); + fflush(stdout); #endif - EXPAND2D(EOFG4); + EXPAND2D(EOFG4); if (EOLcnt) goto EOFG4; - (*sp->fill)(buf, thisrun, pa, lastx); - SETVALUE(0); /* imaginary change for reference */ - SWAP(uint32*, sp->curruns, sp->refruns); - buf += sp->b.rowbytes; - occ -= sp->b.rowbytes; - sp->line++; - continue; - EOFG4: + (*sp->fill)(buf, thisrun, pa, lastx); + SETVALUE(0); /* imaginary change for reference */ + SWAP(uint32*, sp->curruns, sp->refruns); + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + sp->line++; + continue; + EOFG4: NeedBits16( 13, BADG4 ); BADG4: #ifdef FAX3_DEBUG if( GetBits(13) != 0x1001 ) fputs( "Bad EOFB\n", stderr ); -#endif +#endif ClrBits( 13 ); - (*sp->fill)(buf, thisrun, pa, lastx); - UNCACHE_STATE(tif, sp); - return ( sp->line ? 1 : -1); /* don't error on badly-terminated strips */ - } - UNCACHE_STATE(tif, sp); - return (1); + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return ( sp->line ? 1 : -1); /* don't error on badly-terminated strips */ + } + UNCACHE_STATE(tif, sp); + return (1); } #undef SWAP @@ -1432,65 +1485,65 @@ Fax4Decode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) static int Fax4Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - static const char module[] = "Fax4Encode"; - Fax3CodecState *sp = EncoderState(tif); - (void) s; - if (cc % sp->b.rowbytes) - { - TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be written"); - return (0); - } - while (cc > 0) { - if (!Fax3Encode2DRow(tif, bp, sp->refline, sp->b.rowpixels)) - return (0); - _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes); - bp += sp->b.rowbytes; - cc -= sp->b.rowbytes; - } - return (1); + static const char module[] = "Fax4Encode"; + Fax3CodecState *sp = EncoderState(tif); + (void) s; + if (cc % sp->b.rowbytes) + { + TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be written"); + return (0); + } + while (cc > 0) { + if (!Fax3Encode2DRow(tif, bp, sp->refline, sp->b.rowpixels)) + return (0); + _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes); + bp += sp->b.rowbytes; + cc -= sp->b.rowbytes; + } + return (1); } static int Fax4PostEncode(TIFF* tif) { - Fax3CodecState *sp = EncoderState(tif); + Fax3CodecState *sp = EncoderState(tif); - /* terminate strip w/ EOFB */ - Fax3PutBits(tif, EOL, 12); - Fax3PutBits(tif, EOL, 12); - if (sp->bit != 8) - Fax3FlushBits(tif, sp); - return (1); + /* terminate strip w/ EOFB */ + Fax3PutBits(tif, EOL, 12); + Fax3PutBits(tif, EOL, 12); + if (sp->bit != 8) + Fax3FlushBits(tif, sp); + return (1); } int TIFFInitCCITTFax4(TIFF* tif, int scheme) { - (void) scheme; - if (InitCCITTFax3(tif)) { /* reuse G3 support */ - /* - * Merge codec-specific tag information. - */ - if (!_TIFFMergeFields(tif, fax4Fields, - TIFFArrayCount(fax4Fields))) { - TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax4", - "Merging CCITT Fax 4 codec-specific tags failed"); - return 0; - } + (void) scheme; + if (InitCCITTFax3(tif)) { /* reuse G3 support */ + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, fax4Fields, + TIFFArrayCount(fax4Fields))) { + TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax4", + "Merging CCITT Fax 4 codec-specific tags failed"); + return 0; + } - tif->tif_decoderow = Fax4Decode; - tif->tif_decodestrip = Fax4Decode; - tif->tif_decodetile = Fax4Decode; - tif->tif_encoderow = Fax4Encode; - tif->tif_encodestrip = Fax4Encode; - tif->tif_encodetile = Fax4Encode; - tif->tif_postencode = Fax4PostEncode; - /* - * Suppress RTC at the end of each strip. - */ - return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_NORTC); - } else - return (0); + tif->tif_decoderow = Fax4Decode; + tif->tif_decodestrip = Fax4Decode; + tif->tif_decodetile = Fax4Decode; + tif->tif_encoderow = Fax4Encode; + tif->tif_encodestrip = Fax4Encode; + tif->tif_encodetile = Fax4Encode; + tif->tif_postencode = Fax4PostEncode; + /* + * Suppress RTC at the end of each strip. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_NORTC); + } else + return (0); } /* @@ -1504,84 +1557,84 @@ TIFFInitCCITTFax4(TIFF* tif, int scheme) static int Fax3DecodeRLE(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) { - DECLARE_STATE(tif, sp, "Fax3DecodeRLE"); - int mode = sp->b.mode; - (void) s; - if (occ % sp->b.rowbytes) - { - TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); - return (-1); - } - CACHE_STATE(tif, sp); - thisrun = sp->curruns; - while (occ > 0) { - a0 = 0; - RunLength = 0; - pa = thisrun; + DECLARE_STATE(tif, sp, "Fax3DecodeRLE"); + int mode = sp->b.mode; + (void) s; + if (occ % sp->b.rowbytes) + { + TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); + return (-1); + } + CACHE_STATE(tif, sp); + thisrun = sp->curruns; + while (occ > 0) { + a0 = 0; + RunLength = 0; + pa = thisrun; #ifdef FAX3_DEBUG - printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); - printf("-------------------- %d\n", tif->tif_row); - fflush(stdout); + printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail); + printf("-------------------- %d\n", tif->tif_row); + fflush(stdout); #endif - EXPAND1D(EOFRLE); - (*sp->fill)(buf, thisrun, pa, lastx); - /* - * Cleanup at the end of the row. - */ - if (mode & FAXMODE_BYTEALIGN) { - int n = BitsAvail - (BitsAvail &~ 7); - ClrBits(n); - } else if (mode & FAXMODE_WORDALIGN) { - int n = BitsAvail - (BitsAvail &~ 15); - ClrBits(n); - if (BitsAvail == 0 && !isAligned(cp, uint16)) - cp++; - } - buf += sp->b.rowbytes; - occ -= sp->b.rowbytes; - sp->line++; - continue; - EOFRLE: /* premature EOF */ - (*sp->fill)(buf, thisrun, pa, lastx); - UNCACHE_STATE(tif, sp); - return (-1); - } - UNCACHE_STATE(tif, sp); - return (1); + EXPAND1D(EOFRLE); + (*sp->fill)(buf, thisrun, pa, lastx); + /* + * Cleanup at the end of the row. + */ + if (mode & FAXMODE_BYTEALIGN) { + int n = BitsAvail - (BitsAvail &~ 7); + ClrBits(n); + } else if (mode & FAXMODE_WORDALIGN) { + int n = BitsAvail - (BitsAvail &~ 15); + ClrBits(n); + if (BitsAvail == 0 && !isAligned(cp, uint16)) + cp++; + } + buf += sp->b.rowbytes; + occ -= sp->b.rowbytes; + sp->line++; + continue; + EOFRLE: /* premature EOF */ + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return (-1); + } + UNCACHE_STATE(tif, sp); + return (1); } int TIFFInitCCITTRLE(TIFF* tif, int scheme) { - (void) scheme; - if (InitCCITTFax3(tif)) { /* reuse G3 support */ - tif->tif_decoderow = Fax3DecodeRLE; - tif->tif_decodestrip = Fax3DecodeRLE; - tif->tif_decodetile = Fax3DecodeRLE; - /* - * Suppress RTC+EOLs when encoding and byte-align data. - */ - return TIFFSetField(tif, TIFFTAG_FAXMODE, - FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_BYTEALIGN); - } else - return (0); + (void) scheme; + if (InitCCITTFax3(tif)) { /* reuse G3 support */ + tif->tif_decoderow = Fax3DecodeRLE; + tif->tif_decodestrip = Fax3DecodeRLE; + tif->tif_decodetile = Fax3DecodeRLE; + /* + * Suppress RTC+EOLs when encoding and byte-align data. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, + FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_BYTEALIGN); + } else + return (0); } int TIFFInitCCITTRLEW(TIFF* tif, int scheme) { - (void) scheme; - if (InitCCITTFax3(tif)) { /* reuse G3 support */ - tif->tif_decoderow = Fax3DecodeRLE; - tif->tif_decodestrip = Fax3DecodeRLE; - tif->tif_decodetile = Fax3DecodeRLE; - /* - * Suppress RTC+EOLs when encoding and word-align data. - */ - return TIFFSetField(tif, TIFFTAG_FAXMODE, - FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_WORDALIGN); - } else - return (0); + (void) scheme; + if (InitCCITTFax3(tif)) { /* reuse G3 support */ + tif->tif_decoderow = Fax3DecodeRLE; + tif->tif_decodestrip = Fax3DecodeRLE; + tif->tif_decodetile = Fax3DecodeRLE; + /* + * Suppress RTC+EOLs when encoding and word-align data. + */ + return TIFFSetField(tif, TIFFTAG_FAXMODE, + FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_WORDALIGN); + } else + return (0); } #endif /* CCITT_SUPPORT */ diff --git a/3rdparty/libtiff/tif_fax3.h b/3rdparty/libtiff/tif_fax3.h index bb821e0b12..8a435059c7 100644 --- a/3rdparty/libtiff/tif_fax3.h +++ b/3rdparty/libtiff/tif_fax3.h @@ -1,26 +1,26 @@ -/* $Id: tif_fax3.h,v 1.9 2011-03-10 20:23:07 fwarmerdam Exp $ */ +/* $Id: tif_fax3.h,v 1.13 2016-12-14 18:36:27 faxguy Exp $ */ /* * Copyright (c) 1990-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -39,7 +39,7 @@ /* * To override the default routine used to image decoded - * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC. + * spans one can use the pseudo tag TIFFTAG_FAXFILLFUNC. * The routine must have the type signature given below; * for example: * @@ -81,10 +81,12 @@ extern void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32); #define S_MakeUp 11 #define S_EOL 12 +/* WARNING: do not change the layout of this structure as the HylaFAX software */ +/* really depends on it. See http://bugzilla.maptools.org/show_bug.cgi?id=2636 */ typedef struct { /* state table entry */ - unsigned char State; /* see above */ - unsigned char Width; /* width of code in bits */ - uint32 Param; /* unsigned 32-bit run length in bits */ + unsigned char State; /* see above */ + unsigned char Width; /* width of code in bits */ + uint32 Param; /* unsigned 32-bit run length in bits (holds on 16 bit actually, but cannot be changed. See above warning) */ } TIFFFaxTabEnt; extern const TIFFFaxTabEnt TIFFFaxMainTable[]; @@ -136,36 +138,36 @@ extern const TIFFFaxTabEnt TIFFFaxBlackTable[]; #ifndef NeedBits8 #define NeedBits8(n,eoflab) do { \ if (BitsAvail < (n)) { \ - if (EndOfData()) { \ - if (BitsAvail == 0) /* no valid bits */ \ - goto eoflab; \ - BitsAvail = (n); /* pad with zeros */ \ - } else { \ - BitAcc |= ((uint32) bitmap[*cp++])<State], TabEnt->Param); \ + StateNames[TabEnt->State], TabEnt->Param); \ for (t = 0; t < TabEnt->Width; t++) \ - DEBUG_SHOW; \ + DEBUG_SHOW; \ putchar('\n'); \ fflush(stdout); \ ClrBits(TabEnt->Width); \ @@ -209,9 +211,9 @@ static const char* StateNames[] = { NeedBits16(wid,eoflab); \ TabEnt = tab + GetBits(wid); \ printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \ - StateNames[TabEnt->State], TabEnt->Param); \ + StateNames[TabEnt->State], TabEnt->Param); \ for (t = 0; t < TabEnt->Width; t++) \ - DEBUG_SHOW; \ + DEBUG_SHOW; \ putchar('\n'); \ fflush(stdout); \ ClrBits(TabEnt->Width); \ @@ -258,21 +260,21 @@ static const char* StateNames[] = { */ #define SYNC_EOL(eoflab) do { \ if (EOLcnt == 0) { \ - for (;;) { \ - NeedBits16(11,eoflab); \ - if (GetBits(11) == 0) \ - break; \ - ClrBits(1); \ - } \ + for (;;) { \ + NeedBits16(11,eoflab); \ + if (GetBits(11) == 0) \ + break; \ + ClrBits(1); \ + } \ } \ for (;;) { \ - NeedBits8(8,eoflab); \ - if (GetBits(8)) \ - break; \ - ClrBits(8); \ + NeedBits8(8,eoflab); \ + if (GetBits(8)) \ + break; \ + ClrBits(8); \ } \ while (GetBits(1) == 0) \ - ClrBits(1); \ + ClrBits(1); \ ClrBits(1); /* EOL bit */ \ EOLcnt = 0; /* reset EOL counter/flag */ \ } while (0) @@ -284,21 +286,21 @@ static const char* StateNames[] = { */ #define CLEANUP_RUNS() do { \ if (RunLength) \ - SETVALUE(0); \ + SETVALUE(0); \ if (a0 != lastx) { \ - badlength(a0, lastx); \ - while (a0 > lastx && pa > thisrun) \ - a0 -= *--pa; \ - if (a0 < lastx) { \ - if (a0 < 0) \ - a0 = 0; \ - if ((pa-thisrun)&1) \ - SETVALUE(0); \ - SETVALUE(lastx - a0); \ - } else if (a0 > lastx) { \ - SETVALUE(lastx); \ - SETVALUE(0); \ - } \ + badlength(a0, lastx); \ + while (a0 > lastx && pa > thisrun) \ + a0 -= *--pa; \ + if (a0 < lastx) { \ + if (a0 < 0) \ + a0 = 0; \ + if ((pa-thisrun)&1) \ + SETVALUE(0); \ + SETVALUE(lastx - a0); \ + } else if (a0 > lastx) { \ + SETVALUE(lastx); \ + SETVALUE(0); \ + } \ } \ } while (0) @@ -316,50 +318,50 @@ static const char* StateNames[] = { */ #define EXPAND1D(eoflab) do { \ for (;;) { \ - for (;;) { \ - LOOKUP16(12, TIFFFaxWhiteTable, eof1d); \ - switch (TabEnt->State) { \ - case S_EOL: \ - EOLcnt = 1; \ - goto done1d; \ - case S_TermW: \ - SETVALUE(TabEnt->Param); \ - goto doneWhite1d; \ - case S_MakeUpW: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - unexpected("WhiteTable", a0); \ - goto done1d; \ - } \ - } \ + for (;;) { \ + LOOKUP16(12, TIFFFaxWhiteTable, eof1d); \ + switch (TabEnt->State) { \ + case S_EOL: \ + EOLcnt = 1; \ + goto done1d; \ + case S_TermW: \ + SETVALUE(TabEnt->Param); \ + goto doneWhite1d; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("WhiteTable", a0); \ + goto done1d; \ + } \ + } \ doneWhite1d: \ - if (a0 >= lastx) \ - goto done1d; \ - for (;;) { \ - LOOKUP16(13, TIFFFaxBlackTable, eof1d); \ - switch (TabEnt->State) { \ - case S_EOL: \ - EOLcnt = 1; \ - goto done1d; \ - case S_TermB: \ - SETVALUE(TabEnt->Param); \ - goto doneBlack1d; \ - case S_MakeUpB: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - unexpected("BlackTable", a0); \ - goto done1d; \ - } \ - } \ + if (a0 >= lastx) \ + goto done1d; \ + for (;;) { \ + LOOKUP16(13, TIFFFaxBlackTable, eof1d); \ + switch (TabEnt->State) { \ + case S_EOL: \ + EOLcnt = 1; \ + goto done1d; \ + case S_TermB: \ + SETVALUE(TabEnt->Param); \ + goto doneBlack1d; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + unexpected("BlackTable", a0); \ + goto done1d; \ + } \ + } \ doneBlack1d: \ - if (a0 >= lastx) \ - goto done1d; \ + if (a0 >= lastx) \ + goto done1d; \ if( *(pa-1) == 0 && *(pa-2) == 0 ) \ pa -= 2; \ } \ @@ -377,8 +379,8 @@ done1d: \ */ #define CHECK_b1 do { \ if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \ - b1 += pb[0] + pb[1]; \ - pb += 2; \ + b1 += pb[0] + pb[1]; \ + pb += 2; \ } \ } while (0) @@ -387,143 +389,143 @@ done1d: \ */ #define EXPAND2D(eoflab) do { \ while (a0 < lastx) { \ - LOOKUP8(7, TIFFFaxMainTable, eof2d); \ - switch (TabEnt->State) { \ - case S_Pass: \ - CHECK_b1; \ - b1 += *pb++; \ - RunLength += b1 - a0; \ - a0 = b1; \ - b1 += *pb++; \ - break; \ - case S_Horiz: \ - if ((pa-thisrun)&1) { \ - for (;;) { /* black first */ \ - LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ - switch (TabEnt->State) { \ - case S_TermB: \ - SETVALUE(TabEnt->Param); \ - goto doneWhite2da; \ - case S_MakeUpB: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - goto badBlack2d; \ - } \ - } \ - doneWhite2da:; \ - for (;;) { /* then white */ \ - LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ - switch (TabEnt->State) { \ - case S_TermW: \ - SETVALUE(TabEnt->Param); \ - goto doneBlack2da; \ - case S_MakeUpW: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - goto badWhite2d; \ - } \ - } \ - doneBlack2da:; \ - } else { \ - for (;;) { /* white first */ \ - LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ - switch (TabEnt->State) { \ - case S_TermW: \ - SETVALUE(TabEnt->Param); \ - goto doneWhite2db; \ - case S_MakeUpW: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - goto badWhite2d; \ - } \ - } \ - doneWhite2db:; \ - for (;;) { /* then black */ \ - LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ - switch (TabEnt->State) { \ - case S_TermB: \ - SETVALUE(TabEnt->Param); \ - goto doneBlack2db; \ - case S_MakeUpB: \ - case S_MakeUp: \ - a0 += TabEnt->Param; \ - RunLength += TabEnt->Param; \ - break; \ - default: \ - goto badBlack2d; \ - } \ - } \ - doneBlack2db:; \ - } \ - CHECK_b1; \ - break; \ - case S_V0: \ - CHECK_b1; \ - SETVALUE(b1 - a0); \ - b1 += *pb++; \ - break; \ - case S_VR: \ - CHECK_b1; \ - SETVALUE(b1 - a0 + TabEnt->Param); \ - b1 += *pb++; \ - break; \ - case S_VL: \ - CHECK_b1; \ - if (b1 <= (int) (a0 + TabEnt->Param)) { \ - if (b1 < (int) (a0 + TabEnt->Param) || pa != thisrun) { \ - unexpected("VL", a0); \ - goto eol2d; \ - } \ - } \ - SETVALUE(b1 - a0 - TabEnt->Param); \ - b1 -= *--pb; \ - break; \ - case S_Ext: \ - *pa++ = lastx - a0; \ - extension(a0); \ - goto eol2d; \ - case S_EOL: \ - *pa++ = lastx - a0; \ - NeedBits8(4,eof2d); \ - if (GetBits(4)) \ - unexpected("EOL", a0); \ + LOOKUP8(7, TIFFFaxMainTable, eof2d); \ + switch (TabEnt->State) { \ + case S_Pass: \ + CHECK_b1; \ + b1 += *pb++; \ + RunLength += b1 - a0; \ + a0 = b1; \ + b1 += *pb++; \ + break; \ + case S_Horiz: \ + if ((pa-thisrun)&1) { \ + for (;;) { /* black first */ \ + LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermB: \ + SETVALUE(TabEnt->Param); \ + goto doneWhite2da; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badBlack2d; \ + } \ + } \ + doneWhite2da:; \ + for (;;) { /* then white */ \ + LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermW: \ + SETVALUE(TabEnt->Param); \ + goto doneBlack2da; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badWhite2d; \ + } \ + } \ + doneBlack2da:; \ + } else { \ + for (;;) { /* white first */ \ + LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermW: \ + SETVALUE(TabEnt->Param); \ + goto doneWhite2db; \ + case S_MakeUpW: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badWhite2d; \ + } \ + } \ + doneWhite2db:; \ + for (;;) { /* then black */ \ + LOOKUP16(13, TIFFFaxBlackTable, eof2d); \ + switch (TabEnt->State) { \ + case S_TermB: \ + SETVALUE(TabEnt->Param); \ + goto doneBlack2db; \ + case S_MakeUpB: \ + case S_MakeUp: \ + a0 += TabEnt->Param; \ + RunLength += TabEnt->Param; \ + break; \ + default: \ + goto badBlack2d; \ + } \ + } \ + doneBlack2db:; \ + } \ + CHECK_b1; \ + break; \ + case S_V0: \ + CHECK_b1; \ + SETVALUE(b1 - a0); \ + b1 += *pb++; \ + break; \ + case S_VR: \ + CHECK_b1; \ + SETVALUE(b1 - a0 + TabEnt->Param); \ + b1 += *pb++; \ + break; \ + case S_VL: \ + CHECK_b1; \ + if (b1 <= (int) (a0 + TabEnt->Param)) { \ + if (b1 < (int) (a0 + TabEnt->Param) || pa != thisrun) { \ + unexpected("VL", a0); \ + goto eol2d; \ + } \ + } \ + SETVALUE(b1 - a0 - TabEnt->Param); \ + b1 -= *--pb; \ + break; \ + case S_Ext: \ + *pa++ = lastx - a0; \ + extension(a0); \ + goto eol2d; \ + case S_EOL: \ + *pa++ = lastx - a0; \ + NeedBits8(4,eof2d); \ + if (GetBits(4)) \ + unexpected("EOL", a0); \ ClrBits(4); \ - EOLcnt = 1; \ - goto eol2d; \ - default: \ - badMain2d: \ - unexpected("MainTable", a0); \ - goto eol2d; \ - badBlack2d: \ - unexpected("BlackTable", a0); \ - goto eol2d; \ - badWhite2d: \ - unexpected("WhiteTable", a0); \ - goto eol2d; \ - eof2d: \ - prematureEOF(a0); \ - CLEANUP_RUNS(); \ - goto eoflab; \ - } \ + EOLcnt = 1; \ + goto eol2d; \ + default: \ + badMain2d: \ + unexpected("MainTable", a0); \ + goto eol2d; \ + badBlack2d: \ + unexpected("BlackTable", a0); \ + goto eol2d; \ + badWhite2d: \ + unexpected("WhiteTable", a0); \ + goto eol2d; \ + eof2d: \ + prematureEOF(a0); \ + CLEANUP_RUNS(); \ + goto eoflab; \ + } \ } \ if (RunLength) { \ - if (RunLength + a0 < lastx) { \ - /* expect a final V0 */ \ - NeedBits8(1,eof2d); \ - if (!GetBits(1)) \ - goto badMain2d; \ - ClrBits(1); \ - } \ - SETVALUE(0); \ + if (RunLength + a0 < lastx) { \ + /* expect a final V0 */ \ + NeedBits8(1,eof2d); \ + if (!GetBits(1)) \ + goto badMain2d; \ + ClrBits(1); \ + } \ + SETVALUE(0); \ } \ eol2d: \ CLEANUP_RUNS(); \ diff --git a/3rdparty/libtiff/tif_flush.c b/3rdparty/libtiff/tif_flush.c index 75b2425a16..fd14e4cdae 100644 --- a/3rdparty/libtiff/tif_flush.c +++ b/3rdparty/libtiff/tif_flush.c @@ -4,23 +4,23 @@ * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -37,25 +37,25 @@ TIFFFlush(TIFF* tif) if (!TIFFFlushData(tif)) return (0); - - /* In update (r+) mode we try to detect the case where - only the strip/tile map has been altered, and we try to - rewrite only that portion of the directory without + + /* In update (r+) mode we try to detect the case where + only the strip/tile map has been altered, and we try to + rewrite only that portion of the directory without making any other changes */ - + if( (tif->tif_flags & TIFF_DIRTYSTRIP) - && !(tif->tif_flags & TIFF_DIRTYDIRECT) + && !(tif->tif_flags & TIFF_DIRTYDIRECT) && tif->tif_mode == O_RDWR ) { uint64 *offsets=NULL, *sizes=NULL; if( TIFFIsTiled(tif) ) { - if( TIFFGetField( tif, TIFFTAG_TILEOFFSETS, &offsets ) - && TIFFGetField( tif, TIFFTAG_TILEBYTECOUNTS, &sizes ) - && _TIFFRewriteField( tif, TIFFTAG_TILEOFFSETS, TIFF_LONG8, + if( TIFFGetField( tif, TIFFTAG_TILEOFFSETS, &offsets ) + && TIFFGetField( tif, TIFFTAG_TILEBYTECOUNTS, &sizes ) + && _TIFFRewriteField( tif, TIFFTAG_TILEOFFSETS, TIFF_LONG8, tif->tif_dir.td_nstrips, offsets ) - && _TIFFRewriteField( tif, TIFFTAG_TILEBYTECOUNTS, TIFF_LONG8, + && _TIFFRewriteField( tif, TIFFTAG_TILEBYTECOUNTS, TIFF_LONG8, tif->tif_dir.td_nstrips, sizes ) ) { tif->tif_flags &= ~TIFF_DIRTYSTRIP; @@ -65,11 +65,11 @@ TIFFFlush(TIFF* tif) } else { - if( TIFFGetField( tif, TIFFTAG_STRIPOFFSETS, &offsets ) - && TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &sizes ) - && _TIFFRewriteField( tif, TIFFTAG_STRIPOFFSETS, TIFF_LONG8, + if( TIFFGetField( tif, TIFFTAG_STRIPOFFSETS, &offsets ) + && TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &sizes ) + && _TIFFRewriteField( tif, TIFFTAG_STRIPOFFSETS, TIFF_LONG8, tif->tif_dir.td_nstrips, offsets ) - && _TIFFRewriteField( tif, TIFFTAG_STRIPBYTECOUNTS, TIFF_LONG8, + && _TIFFRewriteField( tif, TIFFTAG_STRIPBYTECOUNTS, TIFF_LONG8, tif->tif_dir.td_nstrips, sizes ) ) { tif->tif_flags &= ~TIFF_DIRTYSTRIP; @@ -79,7 +79,7 @@ TIFFFlush(TIFF* tif) } } - if ((tif->tif_flags & (TIFF_DIRTYDIRECT|TIFF_DIRTYSTRIP)) + if ((tif->tif_flags & (TIFF_DIRTYDIRECT|TIFF_DIRTYSTRIP)) && !TIFFRewriteDirectory(tif)) return (0); @@ -93,19 +93,19 @@ TIFFFlush(TIFF* tif) * is not set, so that TIFFFlush() will proceed to write out the directory. * The documentation says returning 1 is an error indicator, but not having * been writing isn't exactly a an error. Hopefully this doesn't cause - * problems for other people. + * problems for other people. */ int TIFFFlushData(TIFF* tif) { - if ((tif->tif_flags & TIFF_BEENWRITING) == 0) - return (1); - if (tif->tif_flags & TIFF_POSTENCODE) { - tif->tif_flags &= ~TIFF_POSTENCODE; - if (!(*tif->tif_postencode)(tif)) - return (0); - } - return (TIFFFlushData1(tif)); + if ((tif->tif_flags & TIFF_BEENWRITING) == 0) + return (1); + if (tif->tif_flags & TIFF_POSTENCODE) { + tif->tif_flags &= ~TIFF_POSTENCODE; + if (!(*tif->tif_postencode)(tif)) + return (0); + } + return (TIFFFlushData1(tif)); } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_getimage.c b/3rdparty/libtiff/tif_getimage.c index 5d3cfe192a..fc554ccab3 100644 --- a/3rdparty/libtiff/tif_getimage.c +++ b/3rdparty/libtiff/tif_getimage.c @@ -1,26 +1,26 @@ -/* $Id: tif_getimage.c,v 1.82 2012-06-06 00:17:49 fwarmerdam Exp $ */ +/* $Id: tif_getimage.c,v 1.114 2017-11-17 20:21:00 erouault Exp $ */ /* * Copyright (c) 1991-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -44,7 +44,7 @@ static int BuildMapBitdepth16To8(TIFFRGBAImage* img); static const char photoTag[] = "PhotometricInterpretation"; -/* +/* * Helper constants used in Orientation tag handling */ #define FLIP_VERTICALLY 0x01 @@ -55,15 +55,15 @@ static const char photoTag[] = "PhotometricInterpretation"; */ static const TIFFDisplay display_sRGB = { - { /* XYZ -> luminance matrix */ - { 3.2410F, -1.5374F, -0.4986F }, - { -0.9692F, 1.8760F, 0.0416F }, - { 0.0556F, -0.2040F, 1.0570F } - }, - 100.0F, 100.0F, 100.0F, /* Light o/p for reference white */ - 255, 255, 255, /* Pixel values for ref. white */ - 1.0F, 1.0F, 1.0F, /* Residual light o/p for black pixel */ - 2.4F, 2.4F, 2.4F, /* Gamma values for the three guns */ + { /* XYZ -> luminance matrix */ + { 3.2410F, -1.5374F, -0.4986F }, + { -0.9692F, 1.8760F, 0.0416F }, + { 0.0556F, -0.2040F, 1.0570F } + }, + 100.0F, 100.0F, 100.0F, /* Light o/p for reference white */ + 255, 255, 255, /* Pixel values for ref. white */ + 1.0F, 1.0F, 1.0F, /* Residual light o/p for black pixel */ + 2.4F, 2.4F, 2.4F, /* Gamma values for the three guns */ }; /* @@ -75,148 +75,181 @@ static const TIFFDisplay display_sRGB = { int TIFFRGBAImageOK(TIFF* tif, char emsg[1024]) { - TIFFDirectory* td = &tif->tif_dir; - uint16 photometric; - int colorchannels; + TIFFDirectory* td = &tif->tif_dir; + uint16 photometric; + int colorchannels; - if (!tif->tif_decodestatus) { - sprintf(emsg, "Sorry, requested compression method is not configured"); - return (0); - } - switch (td->td_bitspersample) { - case 1: - case 2: - case 4: - case 8: - case 16: - break; - default: - sprintf(emsg, "Sorry, can not handle images with %d-bit samples", - td->td_bitspersample); - return (0); - } - colorchannels = td->td_samplesperpixel - td->td_extrasamples; - if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) { - switch (colorchannels) { - case 1: - photometric = PHOTOMETRIC_MINISBLACK; - break; - case 3: - photometric = PHOTOMETRIC_RGB; - break; - default: - sprintf(emsg, "Missing needed %s tag", photoTag); + if (!tif->tif_decodestatus) { + sprintf(emsg, "Sorry, requested compression method is not configured"); + return (0); + } + switch (td->td_bitspersample) { + case 1: + case 2: + case 4: + case 8: + case 16: + break; + default: + sprintf(emsg, "Sorry, can not handle images with %d-bit samples", + td->td_bitspersample); + return (0); + } + if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP) { + sprintf(emsg, "Sorry, can not handle images with IEEE floating-point samples"); return (0); } - } - switch (photometric) { - case PHOTOMETRIC_MINISWHITE: - case PHOTOMETRIC_MINISBLACK: - case PHOTOMETRIC_PALETTE: - if (td->td_planarconfig == PLANARCONFIG_CONTIG - && td->td_samplesperpixel != 1 - && td->td_bitspersample < 8 ) { - sprintf(emsg, - "Sorry, can not handle contiguous data with %s=%d, " - "and %s=%d and Bits/Sample=%d", - photoTag, photometric, - "Samples/pixel", td->td_samplesperpixel, - td->td_bitspersample); - return (0); - } - /* - * We should likely validate that any extra samples are either - * to be ignored, or are alpha, and if alpha we should try to use - * them. But for now we won't bother with this. - */ - break; - case PHOTOMETRIC_YCBCR: - /* - * TODO: if at all meaningful and useful, make more complete - * support check here, or better still, refactor to let supporting - * code decide whether there is support and what meaningfull - * error to return - */ - break; - case PHOTOMETRIC_RGB: - if (colorchannels < 3) { - sprintf(emsg, "Sorry, can not handle RGB image with %s=%d", - "Color channels", colorchannels); - return (0); - } - break; - case PHOTOMETRIC_SEPARATED: - { - uint16 inkset; - TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset); - if (inkset != INKSET_CMYK) { - sprintf(emsg, - "Sorry, can not handle separated image with %s=%d", - "InkSet", inkset); - return 0; - } - if (td->td_samplesperpixel < 4) { - sprintf(emsg, - "Sorry, can not handle separated image with %s=%d", - "Samples/pixel", td->td_samplesperpixel); - return 0; - } - break; - } - case PHOTOMETRIC_LOGL: - if (td->td_compression != COMPRESSION_SGILOG) { - sprintf(emsg, "Sorry, LogL data must have %s=%d", - "Compression", COMPRESSION_SGILOG); - return (0); - } - break; - case PHOTOMETRIC_LOGLUV: - if (td->td_compression != COMPRESSION_SGILOG && - td->td_compression != COMPRESSION_SGILOG24) { - sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d", - "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24); - return (0); - } - if (td->td_planarconfig != PLANARCONFIG_CONTIG) { - sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d", - "Planarconfiguration", td->td_planarconfig); - return (0); - } - break; - case PHOTOMETRIC_CIELAB: - break; - default: - sprintf(emsg, "Sorry, can not handle image with %s=%d", - photoTag, photometric); - return (0); - } - return (1); + colorchannels = td->td_samplesperpixel - td->td_extrasamples; + if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) { + switch (colorchannels) { + case 1: + photometric = PHOTOMETRIC_MINISBLACK; + break; + case 3: + photometric = PHOTOMETRIC_RGB; + break; + default: + sprintf(emsg, "Missing needed %s tag", photoTag); + return (0); + } + } + switch (photometric) { + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + case PHOTOMETRIC_PALETTE: + if (td->td_planarconfig == PLANARCONFIG_CONTIG + && td->td_samplesperpixel != 1 + && td->td_bitspersample < 8 ) { + sprintf(emsg, + "Sorry, can not handle contiguous data with %s=%d, " + "and %s=%d and Bits/Sample=%d", + photoTag, photometric, + "Samples/pixel", td->td_samplesperpixel, + td->td_bitspersample); + return (0); + } + /* + * We should likely validate that any extra samples are either + * to be ignored, or are alpha, and if alpha we should try to use + * them. But for now we won't bother with this. + */ + break; + case PHOTOMETRIC_YCBCR: + /* + * TODO: if at all meaningful and useful, make more complete + * support check here, or better still, refactor to let supporting + * code decide whether there is support and what meaningful + * error to return + */ + break; + case PHOTOMETRIC_RGB: + if (colorchannels < 3) { + sprintf(emsg, "Sorry, can not handle RGB image with %s=%d", + "Color channels", colorchannels); + return (0); + } + break; + case PHOTOMETRIC_SEPARATED: + { + uint16 inkset; + TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset); + if (inkset != INKSET_CMYK) { + sprintf(emsg, + "Sorry, can not handle separated image with %s=%d", + "InkSet", inkset); + return 0; + } + if (td->td_samplesperpixel < 4) { + sprintf(emsg, + "Sorry, can not handle separated image with %s=%d", + "Samples/pixel", td->td_samplesperpixel); + return 0; + } + break; + } + case PHOTOMETRIC_LOGL: + if (td->td_compression != COMPRESSION_SGILOG) { + sprintf(emsg, "Sorry, LogL data must have %s=%d", + "Compression", COMPRESSION_SGILOG); + return (0); + } + break; + case PHOTOMETRIC_LOGLUV: + if (td->td_compression != COMPRESSION_SGILOG && + td->td_compression != COMPRESSION_SGILOG24) { + sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d", + "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24); + return (0); + } + if (td->td_planarconfig != PLANARCONFIG_CONTIG) { + sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d", + "Planarconfiguration", td->td_planarconfig); + return (0); + } + if ( td->td_samplesperpixel != 3 || colorchannels != 3 ) { + sprintf(emsg, + "Sorry, can not handle image with %s=%d, %s=%d", + "Samples/pixel", td->td_samplesperpixel, + "colorchannels", colorchannels); + return 0; + } + break; + case PHOTOMETRIC_CIELAB: + if ( td->td_samplesperpixel != 3 || colorchannels != 3 || td->td_bitspersample != 8 ) { + sprintf(emsg, + "Sorry, can not handle image with %s=%d, %s=%d and %s=%d", + "Samples/pixel", td->td_samplesperpixel, + "colorchannels", colorchannels, + "Bits/sample", td->td_bitspersample); + return 0; + } + break; + default: + sprintf(emsg, "Sorry, can not handle image with %s=%d", + photoTag, photometric); + return (0); + } + return (1); } void TIFFRGBAImageEnd(TIFFRGBAImage* img) { - if (img->Map) - _TIFFfree(img->Map), img->Map = NULL; - if (img->BWmap) - _TIFFfree(img->BWmap), img->BWmap = NULL; - if (img->PALmap) - _TIFFfree(img->PALmap), img->PALmap = NULL; - if (img->ycbcr) - _TIFFfree(img->ycbcr), img->ycbcr = NULL; - if (img->cielab) - _TIFFfree(img->cielab), img->cielab = NULL; - if (img->UaToAa) - _TIFFfree(img->UaToAa), img->UaToAa = NULL; - if (img->Bitdepth16To8) - _TIFFfree(img->Bitdepth16To8), img->Bitdepth16To8 = NULL; + if (img->Map) { + _TIFFfree(img->Map); + img->Map = NULL; + } + if (img->BWmap) { + _TIFFfree(img->BWmap); + img->BWmap = NULL; + } + if (img->PALmap) { + _TIFFfree(img->PALmap); + img->PALmap = NULL; + } + if (img->ycbcr) { + _TIFFfree(img->ycbcr); + img->ycbcr = NULL; + } + if (img->cielab) { + _TIFFfree(img->cielab); + img->cielab = NULL; + } + if (img->UaToAa) { + _TIFFfree(img->UaToAa); + img->UaToAa = NULL; + } + if (img->Bitdepth16To8) { + _TIFFfree(img->Bitdepth16To8); + img->Bitdepth16To8 = NULL; + } - if( img->redcmap ) { - _TIFFfree( img->redcmap ); - _TIFFfree( img->greencmap ); - _TIFFfree( img->bluecmap ); + if( img->redcmap ) { + _TIFFfree( img->redcmap ); + _TIFFfree( img->greencmap ); + _TIFFfree( img->bluecmap ); img->redcmap = img->greencmap = img->bluecmap = NULL; - } + } } static int @@ -225,243 +258,243 @@ isCCITTCompression(TIFF* tif) uint16 compress; TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress); return (compress == COMPRESSION_CCITTFAX3 || - compress == COMPRESSION_CCITTFAX4 || - compress == COMPRESSION_CCITTRLE || - compress == COMPRESSION_CCITTRLEW); + compress == COMPRESSION_CCITTFAX4 || + compress == COMPRESSION_CCITTRLE || + compress == COMPRESSION_CCITTRLEW); } int TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) { - uint16* sampleinfo; - uint16 extrasamples; - uint16 planarconfig; - uint16 compress; - int colorchannels; - uint16 *red_orig, *green_orig, *blue_orig; - int n_color; + uint16* sampleinfo; + uint16 extrasamples; + uint16 planarconfig; + uint16 compress; + int colorchannels; + uint16 *red_orig, *green_orig, *blue_orig; + int n_color; + + if( !TIFFRGBAImageOK(tif, emsg) ) + return 0; - /* Initialize to normal values */ - img->row_offset = 0; - img->col_offset = 0; - img->redcmap = NULL; - img->greencmap = NULL; - img->bluecmap = NULL; - img->req_orientation = ORIENTATION_BOTLEFT; /* It is the default */ + /* Initialize to normal values */ + img->row_offset = 0; + img->col_offset = 0; + img->redcmap = NULL; + img->greencmap = NULL; + img->bluecmap = NULL; + img->Map = NULL; + img->BWmap = NULL; + img->PALmap = NULL; + img->ycbcr = NULL; + img->cielab = NULL; + img->UaToAa = NULL; + img->Bitdepth16To8 = NULL; + img->req_orientation = ORIENTATION_BOTLEFT; /* It is the default */ - img->tif = tif; - img->stoponerr = stop; - TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample); - switch (img->bitspersample) { - case 1: - case 2: - case 4: - case 8: - case 16: - break; - default: - sprintf(emsg, "Sorry, can not handle images with %d-bit samples", - img->bitspersample); - goto fail_return; - } - img->alpha = 0; - TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel); - TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, - &extrasamples, &sampleinfo); - if (extrasamples >= 1) - { - switch (sampleinfo[0]) { - case EXTRASAMPLE_UNSPECIFIED: /* Workaround for some images without */ - if (img->samplesperpixel > 3) /* correct info about alpha channel */ - img->alpha = EXTRASAMPLE_ASSOCALPHA; - break; - case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */ - case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */ - img->alpha = sampleinfo[0]; - break; - } - } + img->tif = tif; + img->stoponerr = stop; + TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample); + switch (img->bitspersample) { + case 1: + case 2: + case 4: + case 8: + case 16: + break; + default: + sprintf(emsg, "Sorry, can not handle images with %d-bit samples", + img->bitspersample); + goto fail_return; + } + img->alpha = 0; + TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel); + TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, + &extrasamples, &sampleinfo); + if (extrasamples >= 1) + { + switch (sampleinfo[0]) { + case EXTRASAMPLE_UNSPECIFIED: /* Workaround for some images without */ + if (img->samplesperpixel > 3) /* correct info about alpha channel */ + img->alpha = EXTRASAMPLE_ASSOCALPHA; + break; + case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */ + case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */ + img->alpha = sampleinfo[0]; + break; + } + } #ifdef DEFAULT_EXTRASAMPLE_AS_ALPHA - if( !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) - img->photometric = PHOTOMETRIC_MINISWHITE; + if( !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) + img->photometric = PHOTOMETRIC_MINISWHITE; - if( extrasamples == 0 - && img->samplesperpixel == 4 - && img->photometric == PHOTOMETRIC_RGB ) - { - img->alpha = EXTRASAMPLE_ASSOCALPHA; - extrasamples = 1; - } + if( extrasamples == 0 + && img->samplesperpixel == 4 + && img->photometric == PHOTOMETRIC_RGB ) + { + img->alpha = EXTRASAMPLE_ASSOCALPHA; + extrasamples = 1; + } #endif - colorchannels = img->samplesperpixel - extrasamples; - TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress); - TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig); - if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) { - switch (colorchannels) { - case 1: - if (isCCITTCompression(tif)) - img->photometric = PHOTOMETRIC_MINISWHITE; - else - img->photometric = PHOTOMETRIC_MINISBLACK; - break; - case 3: - img->photometric = PHOTOMETRIC_RGB; - break; - default: - sprintf(emsg, "Missing needed %s tag", photoTag); + colorchannels = img->samplesperpixel - extrasamples; + TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress); + TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig); + if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) { + switch (colorchannels) { + case 1: + if (isCCITTCompression(tif)) + img->photometric = PHOTOMETRIC_MINISWHITE; + else + img->photometric = PHOTOMETRIC_MINISBLACK; + break; + case 3: + img->photometric = PHOTOMETRIC_RGB; + break; + default: + sprintf(emsg, "Missing needed %s tag", photoTag); goto fail_return; - } - } - switch (img->photometric) { - case PHOTOMETRIC_PALETTE: - if (!TIFFGetField(tif, TIFFTAG_COLORMAP, - &red_orig, &green_orig, &blue_orig)) { - sprintf(emsg, "Missing required \"Colormap\" tag"); + } + } + switch (img->photometric) { + case PHOTOMETRIC_PALETTE: + if (!TIFFGetField(tif, TIFFTAG_COLORMAP, + &red_orig, &green_orig, &blue_orig)) { + sprintf(emsg, "Missing required \"Colormap\" tag"); goto fail_return; - } + } - /* copy the colormaps so we can modify them */ - n_color = (1L << img->bitspersample); - img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); - img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); - img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); - if( !img->redcmap || !img->greencmap || !img->bluecmap ) { - sprintf(emsg, "Out of memory for colormap copy"); + /* copy the colormaps so we can modify them */ + n_color = (1U << img->bitspersample); + img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); + img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); + img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); + if( !img->redcmap || !img->greencmap || !img->bluecmap ) { + sprintf(emsg, "Out of memory for colormap copy"); goto fail_return; - } + } - _TIFFmemcpy( img->redcmap, red_orig, n_color * 2 ); - _TIFFmemcpy( img->greencmap, green_orig, n_color * 2 ); - _TIFFmemcpy( img->bluecmap, blue_orig, n_color * 2 ); + _TIFFmemcpy( img->redcmap, red_orig, n_color * 2 ); + _TIFFmemcpy( img->greencmap, green_orig, n_color * 2 ); + _TIFFmemcpy( img->bluecmap, blue_orig, n_color * 2 ); - /* fall thru... */ - case PHOTOMETRIC_MINISWHITE: - case PHOTOMETRIC_MINISBLACK: - if (planarconfig == PLANARCONFIG_CONTIG - && img->samplesperpixel != 1 - && img->bitspersample < 8 ) { - sprintf(emsg, - "Sorry, can not handle contiguous data with %s=%d, " - "and %s=%d and Bits/Sample=%d", - photoTag, img->photometric, - "Samples/pixel", img->samplesperpixel, - img->bitspersample); + /* fall through... */ + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + if (planarconfig == PLANARCONFIG_CONTIG + && img->samplesperpixel != 1 + && img->bitspersample < 8 ) { + sprintf(emsg, + "Sorry, can not handle contiguous data with %s=%d, " + "and %s=%d and Bits/Sample=%d", + photoTag, img->photometric, + "Samples/pixel", img->samplesperpixel, + img->bitspersample); goto fail_return; - } - break; - case PHOTOMETRIC_YCBCR: - /* It would probably be nice to have a reality check here. */ - if (planarconfig == PLANARCONFIG_CONTIG) - /* can rely on libjpeg to convert to RGB */ - /* XXX should restore current state on exit */ - switch (compress) { - case COMPRESSION_JPEG: - /* - * TODO: when complete tests verify complete desubsampling - * and YCbCr handling, remove use of TIFFTAG_JPEGCOLORMODE in - * favor of tif_getimage.c native handling - */ - TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); - img->photometric = PHOTOMETRIC_RGB; - break; - default: - /* do nothing */; - break; - } - /* - * TODO: if at all meaningful and useful, make more complete - * support check here, or better still, refactor to let supporting - * code decide whether there is support and what meaningfull - * error to return - */ - break; - case PHOTOMETRIC_RGB: - if (colorchannels < 3) { - sprintf(emsg, "Sorry, can not handle RGB image with %s=%d", - "Color channels", colorchannels); + } + break; + case PHOTOMETRIC_YCBCR: + /* It would probably be nice to have a reality check here. */ + if (planarconfig == PLANARCONFIG_CONTIG) + /* can rely on libjpeg to convert to RGB */ + /* XXX should restore current state on exit */ + switch (compress) { + case COMPRESSION_JPEG: + /* + * TODO: when complete tests verify complete desubsampling + * and YCbCr handling, remove use of TIFFTAG_JPEGCOLORMODE in + * favor of tif_getimage.c native handling + */ + TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); + img->photometric = PHOTOMETRIC_RGB; + break; + default: + /* do nothing */; + break; + } + /* + * TODO: if at all meaningful and useful, make more complete + * support check here, or better still, refactor to let supporting + * code decide whether there is support and what meaningful + * error to return + */ + break; + case PHOTOMETRIC_RGB: + if (colorchannels < 3) { + sprintf(emsg, "Sorry, can not handle RGB image with %s=%d", + "Color channels", colorchannels); goto fail_return; - } - break; - case PHOTOMETRIC_SEPARATED: - { - uint16 inkset; - TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset); - if (inkset != INKSET_CMYK) { - sprintf(emsg, "Sorry, can not handle separated image with %s=%d", - "InkSet", inkset); + } + break; + case PHOTOMETRIC_SEPARATED: + { + uint16 inkset; + TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset); + if (inkset != INKSET_CMYK) { + sprintf(emsg, "Sorry, can not handle separated image with %s=%d", + "InkSet", inkset); goto fail_return; - } - if (img->samplesperpixel < 4) { - sprintf(emsg, "Sorry, can not handle separated image with %s=%d", - "Samples/pixel", img->samplesperpixel); + } + if (img->samplesperpixel < 4) { + sprintf(emsg, "Sorry, can not handle separated image with %s=%d", + "Samples/pixel", img->samplesperpixel); goto fail_return; - } - } - break; - case PHOTOMETRIC_LOGL: - if (compress != COMPRESSION_SGILOG) { - sprintf(emsg, "Sorry, LogL data must have %s=%d", - "Compression", COMPRESSION_SGILOG); + } + } + break; + case PHOTOMETRIC_LOGL: + if (compress != COMPRESSION_SGILOG) { + sprintf(emsg, "Sorry, LogL data must have %s=%d", + "Compression", COMPRESSION_SGILOG); goto fail_return; - } - TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); - img->photometric = PHOTOMETRIC_MINISBLACK; /* little white lie */ - img->bitspersample = 8; - break; - case PHOTOMETRIC_LOGLUV: - if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) { - sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d", - "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24); + } + TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); + img->photometric = PHOTOMETRIC_MINISBLACK; /* little white lie */ + img->bitspersample = 8; + break; + case PHOTOMETRIC_LOGLUV: + if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) { + sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d", + "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24); goto fail_return; - } - if (planarconfig != PLANARCONFIG_CONTIG) { - sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d", - "Planarconfiguration", planarconfig); - return (0); - } - TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); - img->photometric = PHOTOMETRIC_RGB; /* little white lie */ - img->bitspersample = 8; - break; - case PHOTOMETRIC_CIELAB: - break; - default: - sprintf(emsg, "Sorry, can not handle image with %s=%d", - photoTag, img->photometric); + } + if (planarconfig != PLANARCONFIG_CONTIG) { + sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d", + "Planarconfiguration", planarconfig); + return (0); + } + TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); + img->photometric = PHOTOMETRIC_RGB; /* little white lie */ + img->bitspersample = 8; + break; + case PHOTOMETRIC_CIELAB: + break; + default: + sprintf(emsg, "Sorry, can not handle image with %s=%d", + photoTag, img->photometric); goto fail_return; - } - img->Map = NULL; - img->BWmap = NULL; - img->PALmap = NULL; - img->ycbcr = NULL; - img->cielab = NULL; - img->UaToAa = NULL; - img->Bitdepth16To8 = NULL; - TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width); - TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height); - TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation); - img->isContig = - !(planarconfig == PLANARCONFIG_SEPARATE && img->samplesperpixel > 1); - if (img->isContig) { - if (!PickContigCase(img)) { - sprintf(emsg, "Sorry, can not handle image"); - goto fail_return; - } - } else { - if (!PickSeparateCase(img)) { - sprintf(emsg, "Sorry, can not handle image"); - goto fail_return; - } - } - return 1; + } + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height); + TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation); + img->isContig = + !(planarconfig == PLANARCONFIG_SEPARATE && img->samplesperpixel > 1); + if (img->isContig) { + if (!PickContigCase(img)) { + sprintf(emsg, "Sorry, can not handle image"); + goto fail_return; + } + } else { + if (!PickSeparateCase(img)) { + sprintf(emsg, "Sorry, can not handle image"); + goto fail_return; + } + } + return 1; fail_return: - _TIFFfree( img->redcmap ); - _TIFFfree( img->greencmap ); - _TIFFfree( img->bluecmap ); - img->redcmap = img->greencmap = img->bluecmap = NULL; + TIFFRGBAImageEnd( img ); return 0; } @@ -469,13 +502,13 @@ int TIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) { if (img->get == NULL) { - TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No \"get\" routine setup"); - return (0); - } - if (img->put.any == NULL) { - TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), - "No \"put\" routine setupl; probably can not handle image format"); - return (0); + TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No \"get\" routine setup"); + return (0); + } + if (img->put.any == NULL) { + TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), + "No \"put\" routine setupl; probably can not handle image format"); + return (0); } return (*img->get)(img, raster, w, h); } @@ -486,22 +519,22 @@ TIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) */ int TIFFReadRGBAImageOriented(TIFF* tif, - uint32 rwidth, uint32 rheight, uint32* raster, - int orientation, int stop) + uint32 rwidth, uint32 rheight, uint32* raster, + int orientation, int stop) { char emsg[1024] = ""; TIFFRGBAImage img; int ok; - if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop, emsg)) { - img.req_orientation = orientation; - /* XXX verify rwidth and rheight against width and height */ - ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth, - rwidth, img.height); - TIFFRGBAImageEnd(&img); - } else { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); - ok = 0; + if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop, emsg)) { + img.req_orientation = (uint16)orientation; + /* XXX verify rwidth and rheight against width and height */ + ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth, + rwidth, img.height); + TIFFRGBAImageEnd(&img); + } else { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); + ok = 0; } return (ok); } @@ -512,71 +545,71 @@ TIFFReadRGBAImageOriented(TIFF* tif, */ int TIFFReadRGBAImage(TIFF* tif, - uint32 rwidth, uint32 rheight, uint32* raster, int stop) + uint32 rwidth, uint32 rheight, uint32* raster, int stop) { - return TIFFReadRGBAImageOriented(tif, rwidth, rheight, raster, - ORIENTATION_BOTLEFT, stop); + return TIFFReadRGBAImageOriented(tif, rwidth, rheight, raster, + ORIENTATION_BOTLEFT, stop); } -static int +static int setorientation(TIFFRGBAImage* img) { - switch (img->orientation) { - case ORIENTATION_TOPLEFT: - case ORIENTATION_LEFTTOP: - if (img->req_orientation == ORIENTATION_TOPRIGHT || - img->req_orientation == ORIENTATION_RIGHTTOP) - return FLIP_HORIZONTALLY; - else if (img->req_orientation == ORIENTATION_BOTRIGHT || - img->req_orientation == ORIENTATION_RIGHTBOT) - return FLIP_HORIZONTALLY | FLIP_VERTICALLY; - else if (img->req_orientation == ORIENTATION_BOTLEFT || - img->req_orientation == ORIENTATION_LEFTBOT) - return FLIP_VERTICALLY; - else - return 0; - case ORIENTATION_TOPRIGHT: - case ORIENTATION_RIGHTTOP: - if (img->req_orientation == ORIENTATION_TOPLEFT || - img->req_orientation == ORIENTATION_LEFTTOP) - return FLIP_HORIZONTALLY; - else if (img->req_orientation == ORIENTATION_BOTRIGHT || - img->req_orientation == ORIENTATION_RIGHTBOT) - return FLIP_VERTICALLY; - else if (img->req_orientation == ORIENTATION_BOTLEFT || - img->req_orientation == ORIENTATION_LEFTBOT) - return FLIP_HORIZONTALLY | FLIP_VERTICALLY; - else - return 0; - case ORIENTATION_BOTRIGHT: - case ORIENTATION_RIGHTBOT: - if (img->req_orientation == ORIENTATION_TOPLEFT || - img->req_orientation == ORIENTATION_LEFTTOP) - return FLIP_HORIZONTALLY | FLIP_VERTICALLY; - else if (img->req_orientation == ORIENTATION_TOPRIGHT || - img->req_orientation == ORIENTATION_RIGHTTOP) - return FLIP_VERTICALLY; - else if (img->req_orientation == ORIENTATION_BOTLEFT || - img->req_orientation == ORIENTATION_LEFTBOT) - return FLIP_HORIZONTALLY; - else - return 0; - case ORIENTATION_BOTLEFT: - case ORIENTATION_LEFTBOT: - if (img->req_orientation == ORIENTATION_TOPLEFT || - img->req_orientation == ORIENTATION_LEFTTOP) - return FLIP_VERTICALLY; - else if (img->req_orientation == ORIENTATION_TOPRIGHT || - img->req_orientation == ORIENTATION_RIGHTTOP) - return FLIP_HORIZONTALLY | FLIP_VERTICALLY; - else if (img->req_orientation == ORIENTATION_BOTRIGHT || - img->req_orientation == ORIENTATION_RIGHTBOT) - return FLIP_HORIZONTALLY; - else - return 0; - default: /* NOTREACHED */ - return 0; - } + switch (img->orientation) { + case ORIENTATION_TOPLEFT: + case ORIENTATION_LEFTTOP: + if (img->req_orientation == ORIENTATION_TOPRIGHT || + img->req_orientation == ORIENTATION_RIGHTTOP) + return FLIP_HORIZONTALLY; + else if (img->req_orientation == ORIENTATION_BOTRIGHT || + img->req_orientation == ORIENTATION_RIGHTBOT) + return FLIP_HORIZONTALLY | FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_BOTLEFT || + img->req_orientation == ORIENTATION_LEFTBOT) + return FLIP_VERTICALLY; + else + return 0; + case ORIENTATION_TOPRIGHT: + case ORIENTATION_RIGHTTOP: + if (img->req_orientation == ORIENTATION_TOPLEFT || + img->req_orientation == ORIENTATION_LEFTTOP) + return FLIP_HORIZONTALLY; + else if (img->req_orientation == ORIENTATION_BOTRIGHT || + img->req_orientation == ORIENTATION_RIGHTBOT) + return FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_BOTLEFT || + img->req_orientation == ORIENTATION_LEFTBOT) + return FLIP_HORIZONTALLY | FLIP_VERTICALLY; + else + return 0; + case ORIENTATION_BOTRIGHT: + case ORIENTATION_RIGHTBOT: + if (img->req_orientation == ORIENTATION_TOPLEFT || + img->req_orientation == ORIENTATION_LEFTTOP) + return FLIP_HORIZONTALLY | FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_TOPRIGHT || + img->req_orientation == ORIENTATION_RIGHTTOP) + return FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_BOTLEFT || + img->req_orientation == ORIENTATION_LEFTBOT) + return FLIP_HORIZONTALLY; + else + return 0; + case ORIENTATION_BOTLEFT: + case ORIENTATION_LEFTBOT: + if (img->req_orientation == ORIENTATION_TOPLEFT || + img->req_orientation == ORIENTATION_LEFTTOP) + return FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_TOPRIGHT || + img->req_orientation == ORIENTATION_RIGHTTOP) + return FLIP_HORIZONTALLY | FLIP_VERTICALLY; + else if (img->req_orientation == ORIENTATION_BOTRIGHT || + img->req_orientation == ORIENTATION_RIGHTBOT) + return FLIP_HORIZONTALLY; + else + return 0; + default: /* NOTREACHED */ + return 0; + } } /* @@ -584,7 +617,7 @@ setorientation(TIFFRGBAImage* img) * PlanarConfiguration contiguous if SamplesPerPixel > 1 * or * SamplesPerPixel == 1 - */ + */ static int gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) { @@ -593,80 +626,100 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) uint32 col, row, y, rowstoread; tmsize_t pos; uint32 tw, th; - unsigned char* buf; + unsigned char* buf = NULL; int32 fromskew, toskew; uint32 nrow; int ret = 1, flip; + uint32 this_tw, tocol; + int32 this_toskew, leftmost_toskew; + int32 leftmost_fromskew; + uint32 leftmost_tw; + tmsize_t bufsize; - buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif)); - if (buf == 0) { + bufsize = TIFFTileSize(tif); + if (bufsize == 0) { TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer"); return (0); } - _TIFFmemset(buf, 0, TIFFTileSize(tif)); + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); flip = setorientation(img); if (flip & FLIP_VERTICALLY) { - y = h - 1; - toskew = -(int32)(tw + w); + y = h - 1; + toskew = -(int32)(tw + w); } else { - y = 0; - toskew = -(int32)(tw - w); + y = 0; + toskew = -(int32)(tw - w); } - - for (row = 0; row < h; row += nrow) + + /* + * Leftmost tile is clipped on left side if col_offset > 0. + */ + leftmost_fromskew = img->col_offset % tw; + leftmost_tw = tw - leftmost_fromskew; + leftmost_toskew = toskew + leftmost_fromskew; + for (row = 0; ret != 0 && row < h; row += nrow) { rowstoread = th - (row + img->row_offset) % th; - nrow = (row + rowstoread > h ? h - row : rowstoread); - for (col = 0; col < w; col += tw) + nrow = (row + rowstoread > h ? h - row : rowstoread); + fromskew = leftmost_fromskew; + this_tw = leftmost_tw; + this_toskew = leftmost_toskew; + tocol = 0; + col = img->col_offset; + while (tocol < w) { - if (TIFFReadTile(tif, buf, col+img->col_offset, - row+img->row_offset, 0, 0)==(tmsize_t)(-1) && img->stoponerr) + if (_TIFFReadTileAndAllocBuffer(tif, (void**) &buf, bufsize, col, + row+img->row_offset, 0, 0)==(tmsize_t)(-1) && + (buf == NULL || img->stoponerr)) { ret = 0; break; } + pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif) + \ + ((tmsize_t) fromskew * img->samplesperpixel); + if (tocol + this_tw > w) + { + /* + * Rightmost tile is clipped on right side. + */ + fromskew = tw - (w - tocol); + this_tw = tw - fromskew; + this_toskew = toskew + fromskew; + } + (*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, buf + pos); + tocol += this_tw; + col += this_tw; + /* + * After the leftmost tile, tiles are no longer clipped on left side. + */ + fromskew = 0; + this_tw = tw; + this_toskew = toskew; + } - pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif); - - if (col + tw > w) - { - /* - * Tile is clipped horizontally. Calculate - * visible portion and skewing factors. - */ - uint32 npix = w - col; - fromskew = tw - npix; - (*put)(img, raster+y*w+col, col, y, - npix, nrow, fromskew, toskew + fromskew, buf + pos); - } - else - { - (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf + pos); - } - } - - y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); + y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow); } _TIFFfree(buf); if (flip & FLIP_HORIZONTALLY) { - uint32 line; + uint32 line; - for (line = 0; line < h; line++) { - uint32 *left = raster + (line * w); - uint32 *right = left + w - 1; - - while ( left < right ) { - uint32 temp = *left; - *left = *right; - *right = temp; - left++, right--; - } - } + for (line = 0; line < h; line++) { + uint32 *left = raster + (line * w); + uint32 *right = left + w - 1; + + while ( left < right ) { + uint32 temp = *left; + *left = *right; + *right = temp; + left++; + right--; + } + } } return (ret); @@ -677,56 +730,51 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) * SamplesPerPixel > 1 * PlanarConfiguration separated * We assume that all such images are RGB. - */ + */ static int gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) { - TIFF* tif = img->tif; - tileSeparateRoutine put = img->put.separate; - uint32 col, row, y, rowstoread; - tmsize_t pos; - uint32 tw, th; - unsigned char* buf; - unsigned char* p0; - unsigned char* p1; - unsigned char* p2; - unsigned char* pa; - tmsize_t tilesize; - tmsize_t bufsize; - int32 fromskew, toskew; - int alpha = img->alpha; - uint32 nrow; - int ret = 1, flip; - int colorchannels; + TIFF* tif = img->tif; + tileSeparateRoutine put = img->put.separate; + uint32 col, row, y, rowstoread; + tmsize_t pos; + uint32 tw, th; + unsigned char* buf = NULL; + unsigned char* p0 = NULL; + unsigned char* p1 = NULL; + unsigned char* p2 = NULL; + unsigned char* pa = NULL; + tmsize_t tilesize; + tmsize_t bufsize; + int32 fromskew, toskew; + int alpha = img->alpha; + uint32 nrow; + int ret = 1, flip; + uint16 colorchannels; + uint32 this_tw, tocol; + int32 this_toskew, leftmost_toskew; + int32 leftmost_fromskew; + uint32 leftmost_tw; - tilesize = TIFFTileSize(tif); - bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,tilesize); - if (bufsize == 0) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtTileSeparate"); - return (0); - } - buf = (unsigned char*) _TIFFmalloc(bufsize); - if (buf == 0) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", "No space for tile buffer"); - return (0); - } - _TIFFmemset(buf, 0, bufsize); - p0 = buf; - p1 = p0 + tilesize; - p2 = p1 + tilesize; - pa = (alpha?(p2+tilesize):NULL); - TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); - TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); + tilesize = TIFFTileSize(tif); + bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,tilesize); + if (bufsize == 0) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtTileSeparate"); + return (0); + } - flip = setorientation(img); - if (flip & FLIP_VERTICALLY) { - y = h - 1; - toskew = -(int32)(tw + w); - } - else { - y = 0; - toskew = -(int32)(tw - w); - } + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); + TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); + + flip = setorientation(img); + if (flip & FLIP_VERTICALLY) { + y = h - 1; + toskew = -(int32)(tw + w); + } + else { + y = 0; + toskew = -(int32)(tw - w); + } switch( img->photometric ) { @@ -734,7 +782,6 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_PALETTE: colorchannels = 1; - p2 = p1 = p0; break; default: @@ -742,83 +789,122 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) break; } - for (row = 0; row < h; row += nrow) - { - rowstoread = th - (row + img->row_offset) % th; - nrow = (row + rowstoread > h ? h - row : rowstoread); - for (col = 0; col < w; col += tw) - { - if (TIFFReadTile(tif, p0, col+img->col_offset, - row+img->row_offset,0,0)==(tmsize_t)(-1) && img->stoponerr) - { - ret = 0; - break; - } - if (colorchannels > 1 - && TIFFReadTile(tif, p1, col+img->col_offset, - row+img->row_offset,0,1) == (tmsize_t)(-1) + /* + * Leftmost tile is clipped on left side if col_offset > 0. + */ + leftmost_fromskew = img->col_offset % tw; + leftmost_tw = tw - leftmost_fromskew; + leftmost_toskew = toskew + leftmost_fromskew; + for (row = 0; ret != 0 && row < h; row += nrow) + { + rowstoread = th - (row + img->row_offset) % th; + nrow = (row + rowstoread > h ? h - row : rowstoread); + fromskew = leftmost_fromskew; + this_tw = leftmost_tw; + this_toskew = leftmost_toskew; + tocol = 0; + col = img->col_offset; + while (tocol < w) + { + if( buf == NULL ) + { + if (_TIFFReadTileAndAllocBuffer( + tif, (void**) &buf, bufsize, col, + row+img->row_offset,0,0)==(tmsize_t)(-1) + && (buf == NULL || img->stoponerr)) + { + ret = 0; + break; + } + p0 = buf; + if( colorchannels == 1 ) + { + p2 = p1 = p0; + pa = (alpha?(p0+3*tilesize):NULL); + } + else + { + p1 = p0 + tilesize; + p2 = p1 + tilesize; + pa = (alpha?(p2+tilesize):NULL); + } + } + else if (TIFFReadTile(tif, p0, col, + row+img->row_offset,0,0)==(tmsize_t)(-1) && img->stoponerr) + { + ret = 0; + break; + } + if (colorchannels > 1 + && TIFFReadTile(tif, p1, col, + row+img->row_offset,0,1) == (tmsize_t)(-1) && img->stoponerr) - { - ret = 0; - break; - } - if (colorchannels > 1 - && TIFFReadTile(tif, p2, col+img->col_offset, - row+img->row_offset,0,2) == (tmsize_t)(-1) + { + ret = 0; + break; + } + if (colorchannels > 1 + && TIFFReadTile(tif, p2, col, + row+img->row_offset,0,2) == (tmsize_t)(-1) && img->stoponerr) - { - ret = 0; - break; - } - if (alpha - && TIFFReadTile(tif,pa,col+img->col_offset, - row+img->row_offset,0,colorchannels) == (tmsize_t)(-1) + { + ret = 0; + break; + } + if (alpha + && TIFFReadTile(tif,pa,col, + row+img->row_offset,0,colorchannels) == (tmsize_t)(-1) && img->stoponerr) { ret = 0; break; - } + } - pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif); + pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif) + \ + ((tmsize_t) fromskew * img->samplesperpixel); + if (tocol + this_tw > w) + { + /* + * Rightmost tile is clipped on right side. + */ + fromskew = tw - (w - tocol); + this_tw = tw - fromskew; + this_toskew = toskew + fromskew; + } + (*put)(img, raster+y*w+tocol, tocol, y, this_tw, nrow, fromskew, this_toskew, \ + p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); + tocol += this_tw; + col += this_tw; + /* + * After the leftmost tile, tiles are no longer clipped on left side. + */ + fromskew = 0; + this_tw = tw; + this_toskew = toskew; + } - if (col + tw > w) - { - /* - * Tile is clipped horizontally. Calculate - * visible portion and skewing factors. - */ - uint32 npix = w - col; - fromskew = tw - npix; - (*put)(img, raster+y*w+col, col, y, - npix, nrow, fromskew, toskew + fromskew, - p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); - } else { - (*put)(img, raster+y*w+col, col, y, - tw, nrow, 0, toskew, p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); - } - } + y += ((flip & FLIP_VERTICALLY) ?-(int32) nrow : (int32) nrow); + } - y += (flip & FLIP_VERTICALLY ?-(int32) nrow : (int32) nrow); - } + if (flip & FLIP_HORIZONTALLY) { + uint32 line; - if (flip & FLIP_HORIZONTALLY) { - uint32 line; + for (line = 0; line < h; line++) { + uint32 *left = raster + (line * w); + uint32 *right = left + w - 1; - for (line = 0; line < h; line++) { - uint32 *left = raster + (line * w); - uint32 *right = left + w - 1; + while ( left < right ) { + uint32 temp = *left; + *left = *right; + *right = temp; + left++; + right--; + } + } + } - while ( left < right ) { - uint32 temp = *left; - *left = *right; - *right = temp; - left++, right--; - } - } - } - - _TIFFfree(buf); - return (ret); + _TIFFfree(buf); + return (ret); } /* @@ -826,82 +912,87 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) * PlanarConfiguration contiguous if SamplesPerPixel > 1 * or * SamplesPerPixel == 1 - */ + */ static int gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) { - TIFF* tif = img->tif; - tileContigRoutine put = img->put.contig; - uint32 row, y, nrow, nrowsub, rowstoread; - tmsize_t pos; - unsigned char* buf; - uint32 rowsperstrip; - uint16 subsamplinghor,subsamplingver; - uint32 imagewidth = img->width; - tmsize_t scanline; - int32 fromskew, toskew; - int ret = 1, flip; + TIFF* tif = img->tif; + tileContigRoutine put = img->put.contig; + uint32 row, y, nrow, nrowsub, rowstoread; + tmsize_t pos; + unsigned char* buf = NULL; + uint32 rowsperstrip; + uint16 subsamplinghor,subsamplingver; + uint32 imagewidth = img->width; + tmsize_t scanline; + int32 fromskew, toskew; + int ret = 1, flip; + tmsize_t maxstripsize; - buf = (unsigned char*) _TIFFmalloc(TIFFStripSize(tif)); - if (buf == 0) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); - return (0); - } - _TIFFmemset(buf, 0, TIFFStripSize(tif)); + TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver); + if( subsamplingver == 0 ) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Invalid vertical YCbCr subsampling"); + return (0); + } + + maxstripsize = TIFFStripSize(tif); - flip = setorientation(img); - if (flip & FLIP_VERTICALLY) { - y = h - 1; - toskew = -(int32)(w + w); - } else { - y = 0; - toskew = -(int32)(w - w); - } + flip = setorientation(img); + if (flip & FLIP_VERTICALLY) { + y = h - 1; + toskew = -(int32)(w + w); + } else { + y = 0; + toskew = -(int32)(w - w); + } - TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); - TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver); - scanline = TIFFScanlineSize(tif); - fromskew = (w < imagewidth ? imagewidth - w : 0); - for (row = 0; row < h; row += nrow) - { - rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; - nrow = (row + rowstoread > h ? h - row : rowstoread); - nrowsub = nrow; - if ((nrowsub%subsamplingver)!=0) - nrowsub+=subsamplingver-nrowsub%subsamplingver; - if (TIFFReadEncodedStrip(tif, - TIFFComputeStrip(tif,row+img->row_offset, 0), - buf, - ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline)==(tmsize_t)(-1) - && img->stoponerr) - { - ret = 0; - break; - } + TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); - pos = ((row + img->row_offset) % rowsperstrip) * scanline; - (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos); - y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); - } + scanline = TIFFScanlineSize(tif); + fromskew = (w < imagewidth ? imagewidth - w : 0); + for (row = 0; row < h; row += nrow) + { + rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; + nrow = (row + rowstoread > h ? h - row : rowstoread); + nrowsub = nrow; + if ((nrowsub%subsamplingver)!=0) + nrowsub+=subsamplingver-nrowsub%subsamplingver; + if (_TIFFReadEncodedStripAndAllocBuffer(tif, + TIFFComputeStrip(tif,row+img->row_offset, 0), + (void**)(&buf), + maxstripsize, + ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline)==(tmsize_t)(-1) + && (buf == NULL || img->stoponerr)) + { + ret = 0; + break; + } - if (flip & FLIP_HORIZONTALLY) { - uint32 line; + pos = ((row + img->row_offset) % rowsperstrip) * scanline + \ + ((tmsize_t) img->col_offset * img->samplesperpixel); + (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos); + y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow); + } - for (line = 0; line < h; line++) { - uint32 *left = raster + (line * w); - uint32 *right = left + w - 1; + if (flip & FLIP_HORIZONTALLY) { + uint32 line; - while ( left < right ) { - uint32 temp = *left; - *left = *right; - *right = temp; - left++, right--; - } - } - } + for (line = 0; line < h; line++) { + uint32 *left = raster + (line * w); + uint32 *right = left + w - 1; - _TIFFfree(buf); - return (ret); + while ( left < right ) { + uint32 temp = *left; + *left = *right; + *right = temp; + left++; + right--; + } + } + } + + _TIFFfree(buf); + return (ret); } /* @@ -913,46 +1004,38 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) static int gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) { - TIFF* tif = img->tif; - tileSeparateRoutine put = img->put.separate; - unsigned char *buf; - unsigned char *p0, *p1, *p2, *pa; - uint32 row, y, nrow, rowstoread; - tmsize_t pos; - tmsize_t scanline; - uint32 rowsperstrip, offset_row; - uint32 imagewidth = img->width; - tmsize_t stripsize; - tmsize_t bufsize; - int32 fromskew, toskew; - int alpha = img->alpha; - int ret = 1, flip, colorchannels; + TIFF* tif = img->tif; + tileSeparateRoutine put = img->put.separate; + unsigned char *buf = NULL; + unsigned char *p0 = NULL, *p1 = NULL, *p2 = NULL, *pa = NULL; + uint32 row, y, nrow, rowstoread; + tmsize_t pos; + tmsize_t scanline; + uint32 rowsperstrip, offset_row; + uint32 imagewidth = img->width; + tmsize_t stripsize; + tmsize_t bufsize; + int32 fromskew, toskew; + int alpha = img->alpha; + int ret = 1, flip; + uint16 colorchannels; - stripsize = TIFFStripSize(tif); - bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,stripsize); - if (bufsize == 0) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtStripSeparate"); - return (0); - } - p0 = buf = (unsigned char *)_TIFFmalloc(bufsize); - if (buf == 0) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); - return (0); - } - _TIFFmemset(buf, 0, bufsize); - p1 = p0 + stripsize; - p2 = p1 + stripsize; - pa = (alpha?(p2+stripsize):NULL); + stripsize = TIFFStripSize(tif); + bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,stripsize); + if (bufsize == 0) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtStripSeparate"); + return (0); + } - flip = setorientation(img); - if (flip & FLIP_VERTICALLY) { - y = h - 1; - toskew = -(int32)(w + w); - } - else { - y = 0; - toskew = -(int32)(w - w); - } + flip = setorientation(img); + if (flip & FLIP_VERTICALLY) { + y = h - 1; + toskew = -(int32)(w + w); + } + else { + y = 0; + toskew = -(int32)(w - w); + } switch( img->photometric ) { @@ -960,7 +1043,6 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_PALETTE: colorchannels = 1; - p2 = p1 = p0; break; default: @@ -968,72 +1050,98 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) break; } - TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); - scanline = TIFFScanlineSize(tif); - fromskew = (w < imagewidth ? imagewidth - w : 0); - for (row = 0; row < h; row += nrow) - { - rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; - nrow = (row + rowstoread > h ? h - row : rowstoread); - offset_row = row + img->row_offset; - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), - p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) - && img->stoponerr) - { - ret = 0; - break; - } - if (colorchannels > 1 + TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + scanline = TIFFScanlineSize(tif); + fromskew = (w < imagewidth ? imagewidth - w : 0); + for (row = 0; row < h; row += nrow) + { + rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; + nrow = (row + rowstoread > h ? h - row : rowstoread); + offset_row = row + img->row_offset; + if( buf == NULL ) + { + if (_TIFFReadEncodedStripAndAllocBuffer( + tif, TIFFComputeStrip(tif, offset_row, 0), + (void**) &buf, bufsize, + ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) + && (buf == NULL || img->stoponerr)) + { + ret = 0; + break; + } + p0 = buf; + if( colorchannels == 1 ) + { + p2 = p1 = p0; + pa = (alpha?(p0+3*stripsize):NULL); + } + else + { + p1 = p0 + stripsize; + p2 = p1 + stripsize; + pa = (alpha?(p2+stripsize):NULL); + } + } + else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), + p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) + && img->stoponerr) + { + ret = 0; + break; + } + if (colorchannels > 1 && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1), p1, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) == (tmsize_t)(-1) - && img->stoponerr) - { - ret = 0; - break; - } - if (colorchannels > 1 + && img->stoponerr) + { + ret = 0; + break; + } + if (colorchannels > 1 && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2), p2, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) == (tmsize_t)(-1) - && img->stoponerr) - { - ret = 0; - break; - } - if (alpha) - { - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, colorchannels), - pa, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) - && img->stoponerr) - { - ret = 0; - break; - } - } + && img->stoponerr) + { + ret = 0; + break; + } + if (alpha) + { + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, colorchannels), + pa, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) + && img->stoponerr) + { + ret = 0; + break; + } + } - pos = ((row + img->row_offset) % rowsperstrip) * scanline; - (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos, - p2 + pos, (alpha?(pa+pos):NULL)); - y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); - } + pos = ((row + img->row_offset) % rowsperstrip) * scanline + \ + ((tmsize_t) img->col_offset * img->samplesperpixel); + (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos, + p2 + pos, (alpha?(pa+pos):NULL)); + y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow); + } - if (flip & FLIP_HORIZONTALLY) { - uint32 line; + if (flip & FLIP_HORIZONTALLY) { + uint32 line; - for (line = 0; line < h; line++) { - uint32 *left = raster + (line * w); - uint32 *right = left + w - 1; + for (line = 0; line < h; line++) { + uint32 *left = raster + (line * w); + uint32 *right = left + w - 1; - while ( left < right ) { - uint32 temp = *left; - *left = *right; - *right = temp; - left++, right--; - } - } - } + while ( left < right ) { + uint32 temp = *left; + *left = *right; + *right = temp; + left++; + right--; + } + } + } - _TIFFfree(buf); - return (ret); + _TIFFfree(buf); + return (ret); } /* @@ -1051,61 +1159,65 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) #define REPEAT2(op) op; op #define CASE8(x,op) \ switch (x) { \ - case 7: op; case 6: op; case 5: op; \ - case 4: op; case 3: op; case 2: op; \ + case 7: op; /*-fallthrough*/ \ + case 6: op; /*-fallthrough*/ \ + case 5: op; /*-fallthrough*/ \ + case 4: op; /*-fallthrough*/ \ + case 3: op; /*-fallthrough*/ \ + case 2: op; /*-fallthrough*/ \ case 1: op; \ } -#define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; } +#define CASE4(x,op) switch (x) { case 3: op; /*-fallthrough*/ case 2: op; /*-fallthrough*/ case 1: op; } #define NOP #define UNROLL8(w, op1, op2) { \ uint32 _x; \ for (_x = w; _x >= 8; _x -= 8) { \ - op1; \ - REPEAT8(op2); \ + op1; \ + REPEAT8(op2); \ } \ if (_x > 0) { \ - op1; \ - CASE8(_x,op2); \ + op1; \ + CASE8(_x,op2); \ } \ } #define UNROLL4(w, op1, op2) { \ uint32 _x; \ for (_x = w; _x >= 4; _x -= 4) { \ - op1; \ - REPEAT4(op2); \ + op1; \ + REPEAT4(op2); \ } \ if (_x > 0) { \ - op1; \ - CASE4(_x,op2); \ + op1; \ + CASE4(_x,op2); \ } \ } #define UNROLL2(w, op1, op2) { \ uint32 _x; \ for (_x = w; _x >= 2; _x -= 2) { \ - op1; \ - REPEAT2(op2); \ + op1; \ + REPEAT2(op2); \ } \ if (_x) { \ - op1; \ - op2; \ + op1; \ + op2; \ } \ } - + #define SKEW(r,g,b,skew) { r += skew; g += skew; b += skew; } #define SKEW4(r,g,b,a,skew) { r += skew; g += skew; b += skew; a+= skew; } #define A1 (((uint32)0xffL)<<24) #define PACK(r,g,b) \ - ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|A1) + ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|A1) #define PACK4(r,g,b,a) \ - ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|((uint32)(a)<<24)) + ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|((uint32)(a)<<24)) #define W2B(v) (((v)>>8)&0xff) /* TODO: PACKW should have be made redundant in favor of Bitdepth16To8 LUT */ #define PACKW(r,g,b) \ - ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|A1) + ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|A1) #define PACKW4(r,g,b,a) \ - ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|((uint32)W2B(a)<<24)) + ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|((uint32)W2B(a)<<24)) #define DECLAREContigPutFunc(name) \ static void name(\ @@ -1126,14 +1238,14 @@ DECLAREContigPutFunc(put8bitcmaptile) int samplesperpixel = img->samplesperpixel; (void) y; - while (h-- > 0) { - for (x = w; x-- > 0;) + for( ; h > 0; --h) { + for (x = w; x > 0; --x) { - *cp++ = PALmap[*pp][0]; + *cp++ = PALmap[*pp][0]; pp += samplesperpixel; } - cp += toskew; - pp += fromskew; + cp += toskew; + pp += fromskew; } } @@ -1146,11 +1258,11 @@ DECLAREContigPutFunc(put4bitcmaptile) (void) x; (void) y; fromskew /= 2; - while (h-- > 0) { - uint32* bw; - UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++); - cp += toskew; - pp += fromskew; + for( ; h > 0; --h) { + uint32* bw; + UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; } } @@ -1163,11 +1275,11 @@ DECLAREContigPutFunc(put2bitcmaptile) (void) x; (void) y; fromskew /= 4; - while (h-- > 0) { - uint32* bw; - UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++); - cp += toskew; - pp += fromskew; + for( ; h > 0; --h) { + uint32* bw; + UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; } } @@ -1180,11 +1292,11 @@ DECLAREContigPutFunc(put1bitcmaptile) (void) x; (void) y; fromskew /= 8; - while (h-- > 0) { - uint32* bw; - UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++); - cp += toskew; - pp += fromskew; + for( ; h > 0; --h) { + uint32* bw; + UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; } } @@ -1197,14 +1309,14 @@ DECLAREContigPutFunc(putgreytile) uint32** BWmap = img->BWmap; (void) y; - while (h-- > 0) { - for (x = w; x-- > 0;) + for( ; h > 0; --h) { + for (x = w; x > 0; --x) { - *cp++ = BWmap[*pp][0]; + *cp++ = BWmap[*pp][0]; pp += samplesperpixel; } - cp += toskew; - pp += fromskew; + cp += toskew; + pp += fromskew; } } @@ -1217,14 +1329,14 @@ DECLAREContigPutFunc(putagreytile) uint32** BWmap = img->BWmap; (void) y; - while (h-- > 0) { - for (x = w; x-- > 0;) + for( ; h > 0; --h) { + for (x = w; x > 0; --x) { - *cp++ = BWmap[*pp][0] & (*(pp+1) << 24 | ~A1); + *cp++ = BWmap[*pp][0] & ((uint32)*(pp+1) << 24 | ~A1); pp += samplesperpixel; } - cp += toskew; - pp += fromskew; + cp += toskew; + pp += fromskew; } } @@ -1237,19 +1349,19 @@ DECLAREContigPutFunc(put16bitbwtile) uint32** BWmap = img->BWmap; (void) y; - while (h-- > 0) { + for( ; h > 0; --h) { uint16 *wp = (uint16 *) pp; - for (x = w; x-- > 0;) + for (x = w; x > 0; --x) { /* use high order byte of 16bit value */ - *cp++ = BWmap[*wp >> 8][0]; + *cp++ = BWmap[*wp >> 8][0]; pp += 2 * samplesperpixel; wp += samplesperpixel; } - cp += toskew; - pp += fromskew; + cp += toskew; + pp += fromskew; } } @@ -1262,11 +1374,11 @@ DECLAREContigPutFunc(put1bitbwtile) (void) x; (void) y; fromskew /= 8; - while (h-- > 0) { - uint32* bw; - UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++); - cp += toskew; - pp += fromskew; + for( ; h > 0; --h) { + uint32* bw; + UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; } } @@ -1279,11 +1391,11 @@ DECLAREContigPutFunc(put2bitbwtile) (void) x; (void) y; fromskew /= 4; - while (h-- > 0) { - uint32* bw; - UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++); - cp += toskew; - pp += fromskew; + for( ; h > 0; --h) { + uint32* bw; + UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; } } @@ -1296,11 +1408,11 @@ DECLAREContigPutFunc(put4bitbwtile) (void) x; (void) y; fromskew /= 2; - while (h-- > 0) { - uint32* bw; - UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++); - cp += toskew; - pp += fromskew; + for( ; h > 0; --h) { + uint32* bw; + UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++); + cp += toskew; + pp += fromskew; } } @@ -1313,12 +1425,12 @@ DECLAREContigPutFunc(putRGBcontig8bittile) (void) x; (void) y; fromskew *= samplesperpixel; - while (h-- > 0) { - UNROLL8(w, NOP, - *cp++ = PACK(pp[0], pp[1], pp[2]); - pp += samplesperpixel); - cp += toskew; - pp += fromskew; + for( ; h > 0; --h) { + UNROLL8(w, NOP, + *cp++ = PACK(pp[0], pp[1], pp[2]); + pp += samplesperpixel); + cp += toskew; + pp += fromskew; } } @@ -1332,12 +1444,12 @@ DECLAREContigPutFunc(putRGBAAcontig8bittile) (void) x; (void) y; fromskew *= samplesperpixel; - while (h-- > 0) { - UNROLL8(w, NOP, - *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]); - pp += samplesperpixel); - cp += toskew; - pp += fromskew; + for( ; h > 0; --h) { + UNROLL8(w, NOP, + *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]); + pp += samplesperpixel); + cp += toskew; + pp += fromskew; } } @@ -1347,24 +1459,24 @@ DECLAREContigPutFunc(putRGBAAcontig8bittile) */ DECLAREContigPutFunc(putRGBUAcontig8bittile) { - int samplesperpixel = img->samplesperpixel; - (void) y; - fromskew *= samplesperpixel; - while (h-- > 0) { - uint32 r, g, b, a; - uint8* m; - for (x = w; x-- > 0;) { - a = pp[3]; - m = img->UaToAa+(a<<8); - r = m[pp[0]]; - g = m[pp[1]]; - b = m[pp[2]]; - *cp++ = PACK4(r,g,b,a); - pp += samplesperpixel; - } - cp += toskew; - pp += fromskew; - } + int samplesperpixel = img->samplesperpixel; + (void) y; + fromskew *= samplesperpixel; + for( ; h > 0; --h) { + uint32 r, g, b, a; + uint8* m; + for (x = w; x > 0; --x) { + a = pp[3]; + m = img->UaToAa+((size_t) a<<8); + r = m[pp[0]]; + g = m[pp[1]]; + b = m[pp[2]]; + *cp++ = PACK4(r,g,b,a); + pp += samplesperpixel; + } + cp += toskew; + pp += fromskew; + } } /* @@ -1372,20 +1484,20 @@ DECLAREContigPutFunc(putRGBUAcontig8bittile) */ DECLAREContigPutFunc(putRGBcontig16bittile) { - int samplesperpixel = img->samplesperpixel; - uint16 *wp = (uint16 *)pp; - (void) y; - fromskew *= samplesperpixel; - while (h-- > 0) { - for (x = w; x-- > 0;) { - *cp++ = PACK(img->Bitdepth16To8[wp[0]], - img->Bitdepth16To8[wp[1]], - img->Bitdepth16To8[wp[2]]); - wp += samplesperpixel; - } - cp += toskew; - wp += fromskew; - } + int samplesperpixel = img->samplesperpixel; + uint16 *wp = (uint16 *)pp; + (void) y; + fromskew *= samplesperpixel; + for( ; h > 0; --h) { + for (x = w; x > 0; --x) { + *cp++ = PACK(img->Bitdepth16To8[wp[0]], + img->Bitdepth16To8[wp[1]], + img->Bitdepth16To8[wp[2]]); + wp += samplesperpixel; + } + cp += toskew; + wp += fromskew; + } } /* @@ -1394,21 +1506,21 @@ DECLAREContigPutFunc(putRGBcontig16bittile) */ DECLAREContigPutFunc(putRGBAAcontig16bittile) { - int samplesperpixel = img->samplesperpixel; - uint16 *wp = (uint16 *)pp; - (void) y; - fromskew *= samplesperpixel; - while (h-- > 0) { - for (x = w; x-- > 0;) { - *cp++ = PACK4(img->Bitdepth16To8[wp[0]], - img->Bitdepth16To8[wp[1]], - img->Bitdepth16To8[wp[2]], - img->Bitdepth16To8[wp[3]]); - wp += samplesperpixel; - } - cp += toskew; - wp += fromskew; - } + int samplesperpixel = img->samplesperpixel; + uint16 *wp = (uint16 *)pp; + (void) y; + fromskew *= samplesperpixel; + for( ; h > 0; --h) { + for (x = w; x > 0; --x) { + *cp++ = PACK4(img->Bitdepth16To8[wp[0]], + img->Bitdepth16To8[wp[1]], + img->Bitdepth16To8[wp[2]], + img->Bitdepth16To8[wp[3]]); + wp += samplesperpixel; + } + cp += toskew; + wp += fromskew; + } } /* @@ -1417,25 +1529,25 @@ DECLAREContigPutFunc(putRGBAAcontig16bittile) */ DECLAREContigPutFunc(putRGBUAcontig16bittile) { - int samplesperpixel = img->samplesperpixel; - uint16 *wp = (uint16 *)pp; - (void) y; - fromskew *= samplesperpixel; - while (h-- > 0) { - uint32 r,g,b,a; - uint8* m; - for (x = w; x-- > 0;) { - a = img->Bitdepth16To8[wp[3]]; - m = img->UaToAa+(a<<8); - r = m[img->Bitdepth16To8[wp[0]]]; - g = m[img->Bitdepth16To8[wp[1]]]; - b = m[img->Bitdepth16To8[wp[2]]]; - *cp++ = PACK4(r,g,b,a); - wp += samplesperpixel; - } - cp += toskew; - wp += fromskew; - } + int samplesperpixel = img->samplesperpixel; + uint16 *wp = (uint16 *)pp; + (void) y; + fromskew *= samplesperpixel; + for( ; h > 0; --h) { + uint32 r,g,b,a; + uint8* m; + for (x = w; x > 0; --x) { + a = img->Bitdepth16To8[wp[3]]; + m = img->UaToAa+((size_t) a<<8); + r = m[img->Bitdepth16To8[wp[0]]]; + g = m[img->Bitdepth16To8[wp[1]]]; + b = m[img->Bitdepth16To8[wp[2]]]; + *cp++ = PACK4(r,g,b,a); + wp += samplesperpixel; + } + cp += toskew; + wp += fromskew; + } } /* @@ -1450,16 +1562,16 @@ DECLAREContigPutFunc(putRGBcontig8bitCMYKtile) (void) x; (void) y; fromskew *= samplesperpixel; - while (h-- > 0) { - UNROLL8(w, NOP, - k = 255 - pp[3]; - r = (k*(255-pp[0]))/255; - g = (k*(255-pp[1]))/255; - b = (k*(255-pp[2]))/255; - *cp++ = PACK(r, g, b); - pp += samplesperpixel); - cp += toskew; - pp += fromskew; + for( ; h > 0; --h) { + UNROLL8(w, NOP, + k = 255 - pp[3]; + r = (k*(255-pp[0]))/255; + g = (k*(255-pp[1]))/255; + b = (k*(255-pp[2]))/255; + *cp++ = PACK(r, g, b); + pp += samplesperpixel); + cp += toskew; + pp += fromskew; } } @@ -1476,17 +1588,17 @@ DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile) (void) y; fromskew *= samplesperpixel; - while (h-- > 0) { - for (x = w; x-- > 0;) { - k = 255 - pp[3]; - r = (k*(255-pp[0]))/255; - g = (k*(255-pp[1]))/255; - b = (k*(255-pp[2]))/255; - *cp++ = PACK(Map[r], Map[g], Map[b]); - pp += samplesperpixel; - } - pp += fromskew; - cp += toskew; + for( ; h > 0; --h) { + for (x = w; x > 0; --x) { + k = 255 - pp[3]; + r = (k*(255-pp[0]))/255; + g = (k*(255-pp[1]))/255; + b = (k*(255-pp[2]))/255; + *cp++ = PACK(Map[r], Map[g], Map[b]); + pp += samplesperpixel; + } + pp += fromskew; + cp += toskew; } } @@ -1506,10 +1618,10 @@ static void name(\ DECLARESepPutFunc(putRGBseparate8bittile) { (void) img; (void) x; (void) y; (void) a; - while (h-- > 0) { - UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++)); - SKEW(r, g, b, fromskew); - cp += toskew; + for( ; h > 0; --h) { + UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++)); + SKEW(r, g, b, fromskew); + cp += toskew; } } @@ -1518,12 +1630,12 @@ DECLARESepPutFunc(putRGBseparate8bittile) */ DECLARESepPutFunc(putRGBAAseparate8bittile) { - (void) img; (void) x; (void) y; - while (h-- > 0) { - UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++)); - SKEW4(r, g, b, a, fromskew); - cp += toskew; - } + (void) img; (void) x; (void) y; + for( ; h > 0; --h) { + UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++)); + SKEW4(r, g, b, a, fromskew); + cp += toskew; + } } /* @@ -1531,19 +1643,19 @@ DECLARESepPutFunc(putRGBAAseparate8bittile) */ DECLARESepPutFunc(putCMYKseparate8bittile) { - (void) img; (void) y; - while (h-- > 0) { - uint32 rv, gv, bv, kv; - for (x = w; x-- > 0;) { - kv = 255 - *a++; - rv = (kv*(255-*r++))/255; - gv = (kv*(255-*g++))/255; - bv = (kv*(255-*b++))/255; - *cp++ = PACK4(rv,gv,bv,255); - } - SKEW4(r, g, b, a, fromskew); - cp += toskew; - } + (void) img; (void) y; + for( ; h > 0; --h) { + uint32 rv, gv, bv, kv; + for (x = w; x > 0; --x) { + kv = 255 - *a++; + rv = (kv*(255-*r++))/255; + gv = (kv*(255-*g++))/255; + bv = (kv*(255-*b++))/255; + *cp++ = PACK4(rv,gv,bv,255); + } + SKEW4(r, g, b, a, fromskew); + cp += toskew; + } } /* @@ -1551,21 +1663,21 @@ DECLARESepPutFunc(putCMYKseparate8bittile) */ DECLARESepPutFunc(putRGBUAseparate8bittile) { - (void) img; (void) y; - while (h-- > 0) { - uint32 rv, gv, bv, av; - uint8* m; - for (x = w; x-- > 0;) { - av = *a++; - m = img->UaToAa+(av<<8); - rv = m[*r++]; - gv = m[*g++]; - bv = m[*b++]; - *cp++ = PACK4(rv,gv,bv,av); - } - SKEW4(r, g, b, a, fromskew); - cp += toskew; - } + (void) img; (void) y; + for( ; h > 0; --h) { + uint32 rv, gv, bv, av; + uint8* m; + for (x = w; x > 0; --x) { + av = *a++; + m = img->UaToAa+((size_t) av<<8); + rv = m[*r++]; + gv = m[*g++]; + bv = m[*b++]; + *cp++ = PACK4(rv,gv,bv,av); + } + SKEW4(r, g, b, a, fromskew); + cp += toskew; + } } /* @@ -1573,18 +1685,18 @@ DECLARESepPutFunc(putRGBUAseparate8bittile) */ DECLARESepPutFunc(putRGBseparate16bittile) { - uint16 *wr = (uint16*) r; - uint16 *wg = (uint16*) g; - uint16 *wb = (uint16*) b; - (void) img; (void) y; (void) a; - while (h-- > 0) { - for (x = 0; x < w; x++) - *cp++ = PACK(img->Bitdepth16To8[*wr++], - img->Bitdepth16To8[*wg++], - img->Bitdepth16To8[*wb++]); - SKEW(wr, wg, wb, fromskew); - cp += toskew; - } + uint16 *wr = (uint16*) r; + uint16 *wg = (uint16*) g; + uint16 *wb = (uint16*) b; + (void) img; (void) y; (void) a; + for( ; h > 0; --h) { + for (x = 0; x < w; x++) + *cp++ = PACK(img->Bitdepth16To8[*wr++], + img->Bitdepth16To8[*wg++], + img->Bitdepth16To8[*wb++]); + SKEW(wr, wg, wb, fromskew); + cp += toskew; + } } /* @@ -1592,20 +1704,20 @@ DECLARESepPutFunc(putRGBseparate16bittile) */ DECLARESepPutFunc(putRGBAAseparate16bittile) { - uint16 *wr = (uint16*) r; - uint16 *wg = (uint16*) g; - uint16 *wb = (uint16*) b; - uint16 *wa = (uint16*) a; - (void) img; (void) y; - while (h-- > 0) { - for (x = 0; x < w; x++) - *cp++ = PACK4(img->Bitdepth16To8[*wr++], - img->Bitdepth16To8[*wg++], - img->Bitdepth16To8[*wb++], - img->Bitdepth16To8[*wa++]); - SKEW4(wr, wg, wb, wa, fromskew); - cp += toskew; - } + uint16 *wr = (uint16*) r; + uint16 *wg = (uint16*) g; + uint16 *wb = (uint16*) b; + uint16 *wa = (uint16*) a; + (void) img; (void) y; + for( ; h > 0; --h) { + for (x = 0; x < w; x++) + *cp++ = PACK4(img->Bitdepth16To8[*wr++], + img->Bitdepth16To8[*wg++], + img->Bitdepth16To8[*wb++], + img->Bitdepth16To8[*wa++]); + SKEW4(wr, wg, wb, wa, fromskew); + cp += toskew; + } } /* @@ -1613,25 +1725,25 @@ DECLARESepPutFunc(putRGBAAseparate16bittile) */ DECLARESepPutFunc(putRGBUAseparate16bittile) { - uint16 *wr = (uint16*) r; - uint16 *wg = (uint16*) g; - uint16 *wb = (uint16*) b; - uint16 *wa = (uint16*) a; - (void) img; (void) y; - while (h-- > 0) { - uint32 r,g,b,a; - uint8* m; - for (x = w; x-- > 0;) { - a = img->Bitdepth16To8[*wa++]; - m = img->UaToAa+(a<<8); - r = m[img->Bitdepth16To8[*wr++]]; - g = m[img->Bitdepth16To8[*wg++]]; - b = m[img->Bitdepth16To8[*wb++]]; - *cp++ = PACK4(r,g,b,a); - } - SKEW4(wr, wg, wb, wa, fromskew); - cp += toskew; - } + uint16 *wr = (uint16*) r; + uint16 *wg = (uint16*) g; + uint16 *wb = (uint16*) b; + uint16 *wa = (uint16*) a; + (void) img; (void) y; + for( ; h > 0; --h) { + uint32 r2,g2,b2,a2; + uint8* m; + for (x = w; x > 0; --x) { + a2 = img->Bitdepth16To8[*wa++]; + m = img->UaToAa+((size_t) a2<<8); + r2 = m[img->Bitdepth16To8[*wr++]]; + g2 = m[img->Bitdepth16To8[*wg++]]; + b2 = m[img->Bitdepth16To8[*wb++]]; + *cp++ = PACK4(r2,g2,b2,a2); + } + SKEW4(wr, wg, wb, wa, fromskew); + cp += toskew; + } } /* @@ -1639,24 +1751,24 @@ DECLARESepPutFunc(putRGBUAseparate16bittile) */ DECLAREContigPutFunc(putcontig8bitCIELab) { - float X, Y, Z; - uint32 r, g, b; - (void) y; - fromskew *= 3; - while (h-- > 0) { - for (x = w; x-- > 0;) { - TIFFCIELabToXYZ(img->cielab, - (unsigned char)pp[0], - (signed char)pp[1], - (signed char)pp[2], - &X, &Y, &Z); - TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b); - *cp++ = PACK(r, g, b); - pp += 3; - } - cp += toskew; - pp += fromskew; - } + float X, Y, Z; + uint32 r, g, b; + (void) y; + fromskew *= 3; + for( ; h > 0; --h) { + for (x = w; x > 0; --x) { + TIFFCIELabToXYZ(img->cielab, + (unsigned char)pp[0], + (signed char)pp[1], + (signed char)pp[2], + &X, &Y, &Z); + TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b); + *cp++ = PACK(r, g, b); + pp += 3; + } + cp += toskew; + pp += fromskew; + } } /* @@ -1664,28 +1776,28 @@ DECLAREContigPutFunc(putcontig8bitCIELab) */ #define YCbCrtoRGB(dst, Y) { \ - uint32 r, g, b; \ - TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b); \ - dst = PACK(r, g, b); \ + uint32 r, g, b; \ + TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b); \ + dst = PACK(r, g, b); \ } /* - * 8-bit packed YCbCr samples => RGB - * This function is generic for different sampling sizes, + * 8-bit packed YCbCr samples => RGB + * This function is generic for different sampling sizes, * and can handle blocks sizes that aren't multiples of the * sampling size. However, it is substantially less optimized * than the specific sampling cases. It is used as a fallback * for difficult blocks. */ #ifdef notdef -static void putcontig8bitYCbCrGenericTile( - TIFFRGBAImage* img, - uint32* cp, - uint32 x, uint32 y, - uint32 w, uint32 h, - int32 fromskew, int32 toskew, +static void putcontig8bitYCbCrGenericTile( + TIFFRGBAImage* img, + uint32* cp, + uint32 x, uint32 y, + uint32 w, uint32 h, + int32 fromskew, int32 toskew, unsigned char* pp, - int h_group, + int h_group, int v_group ) { @@ -1705,42 +1817,42 @@ static void putcontig8bitYCbCrGenericTile( int y_line_group = yy / v_group; int y_remainder = yy - y_line_group * v_group; - pp_line = pp + v_line_group * - + pp_line = pp + v_line_group * + for( xx = 0; xx < w; xx++ ) { Cb = pp } } for (; h >= 4; h -= 4) { - x = w>>2; - do { - Cb = pp[16]; - Cr = pp[17]; + x = w>>2; + do { + Cb = pp[16]; + Cr = pp[17]; - YCbCrtoRGB(cp [0], pp[ 0]); - YCbCrtoRGB(cp [1], pp[ 1]); - YCbCrtoRGB(cp [2], pp[ 2]); - YCbCrtoRGB(cp [3], pp[ 3]); - YCbCrtoRGB(cp1[0], pp[ 4]); - YCbCrtoRGB(cp1[1], pp[ 5]); - YCbCrtoRGB(cp1[2], pp[ 6]); - YCbCrtoRGB(cp1[3], pp[ 7]); - YCbCrtoRGB(cp2[0], pp[ 8]); - YCbCrtoRGB(cp2[1], pp[ 9]); - YCbCrtoRGB(cp2[2], pp[10]); - YCbCrtoRGB(cp2[3], pp[11]); - YCbCrtoRGB(cp3[0], pp[12]); - YCbCrtoRGB(cp3[1], pp[13]); - YCbCrtoRGB(cp3[2], pp[14]); - YCbCrtoRGB(cp3[3], pp[15]); + YCbCrtoRGB(cp [0], pp[ 0]); + YCbCrtoRGB(cp [1], pp[ 1]); + YCbCrtoRGB(cp [2], pp[ 2]); + YCbCrtoRGB(cp [3], pp[ 3]); + YCbCrtoRGB(cp1[0], pp[ 4]); + YCbCrtoRGB(cp1[1], pp[ 5]); + YCbCrtoRGB(cp1[2], pp[ 6]); + YCbCrtoRGB(cp1[3], pp[ 7]); + YCbCrtoRGB(cp2[0], pp[ 8]); + YCbCrtoRGB(cp2[1], pp[ 9]); + YCbCrtoRGB(cp2[2], pp[10]); + YCbCrtoRGB(cp2[3], pp[11]); + YCbCrtoRGB(cp3[0], pp[12]); + YCbCrtoRGB(cp3[1], pp[13]); + YCbCrtoRGB(cp3[2], pp[14]); + YCbCrtoRGB(cp3[3], pp[15]); - cp += 4, cp1 += 4, cp2 += 4, cp3 += 4; - pp += 18; - } while (--x); - cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; - pp += fromskew; + cp += 4, cp1 += 4, cp2 += 4, cp3 += 4; + pp += 18; + } while (--x); + cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; + pp += fromskew; } } #endif @@ -1757,8 +1869,8 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile) (void) y; /* adjust fromskew */ - fromskew = (fromskew * 18) / 4; - if ((h & 3) == 0 && (w & 3) == 0) { + fromskew = (fromskew / 4) * (4*2+2); + if ((h & 3) == 0 && (w & 3) == 0) { for (; h >= 4; h -= 4) { x = w>>2; do { @@ -1782,10 +1894,16 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile) YCbCrtoRGB(cp3[2], pp[14]); YCbCrtoRGB(cp3[3], pp[15]); - cp += 4, cp1 += 4, cp2 += 4, cp3 += 4; + cp += 4; + cp1 += 4; + cp2 += 4; + cp3 += 4; pp += 18; } while (--x); - cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; + cp += incr; + cp1 += incr; + cp2 += incr; + cp3 += incr; pp += fromskew; } } else { @@ -1836,7 +1954,10 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile) if (h <= 4) break; h -= 4; - cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; + cp += incr; + cp1 += incr; + cp2 += incr; + cp3 += incr; pp += fromskew; } } @@ -1851,14 +1972,14 @@ DECLAREContigPutFunc(putcontig8bitYCbCr42tile) int32 incr = 2*toskew+w; (void) y; - fromskew = (fromskew * 10) / 4; - if ((h & 3) == 0 && (w & 1) == 0) { + fromskew = (fromskew / 4) * (4*2+2); + if ((w & 3) == 0 && (h & 1) == 0) { for (; h >= 2; h -= 2) { x = w>>2; do { int32 Cb = pp[8]; int32 Cr = pp[9]; - + YCbCrtoRGB(cp [0], pp[0]); YCbCrtoRGB(cp [1], pp[1]); YCbCrtoRGB(cp [2], pp[2]); @@ -1867,11 +1988,13 @@ DECLAREContigPutFunc(putcontig8bitYCbCr42tile) YCbCrtoRGB(cp1[1], pp[5]); YCbCrtoRGB(cp1[2], pp[6]); YCbCrtoRGB(cp1[3], pp[7]); - - cp += 4, cp1 += 4; + + cp += 4; + cp1 += 4; pp += 10; } while (--x); - cp += incr, cp1 += incr; + cp += incr; + cp1 += incr; pp += fromskew; } } else { @@ -1914,7 +2037,8 @@ DECLAREContigPutFunc(putcontig8bitYCbCr42tile) if (h <= 2) break; h -= 2; - cp += incr, cp1 += incr; + cp += incr; + cp1 += incr; pp += fromskew; } } @@ -1926,31 +2050,32 @@ DECLAREContigPutFunc(putcontig8bitYCbCr42tile) DECLAREContigPutFunc(putcontig8bitYCbCr41tile) { (void) y; - /* XXX adjust fromskew */ + fromskew = (fromskew / 4) * (4*1+2); do { - x = w>>2; - do { - int32 Cb = pp[4]; - int32 Cr = pp[5]; + x = w>>2; + while(x>0) { + int32 Cb = pp[4]; + int32 Cr = pp[5]; - YCbCrtoRGB(cp [0], pp[0]); - YCbCrtoRGB(cp [1], pp[1]); - YCbCrtoRGB(cp [2], pp[2]); - YCbCrtoRGB(cp [3], pp[3]); + YCbCrtoRGB(cp [0], pp[0]); + YCbCrtoRGB(cp [1], pp[1]); + YCbCrtoRGB(cp [2], pp[2]); + YCbCrtoRGB(cp [3], pp[3]); - cp += 4; - pp += 6; - } while (--x); + cp += 4; + pp += 6; + x--; + } if( (w&3) != 0 ) { - int32 Cb = pp[4]; - int32 Cr = pp[5]; + int32 Cb = pp[4]; + int32 Cr = pp[5]; switch( (w&3) ) { - case 3: YCbCrtoRGB(cp [2], pp[2]); - case 2: YCbCrtoRGB(cp [1], pp[1]); - case 1: YCbCrtoRGB(cp [0], pp[0]); + case 3: YCbCrtoRGB(cp [2], pp[2]); /*-fallthrough*/ + case 2: YCbCrtoRGB(cp [1], pp[1]); /*-fallthrough*/ + case 1: YCbCrtoRGB(cp [0], pp[0]); /*-fallthrough*/ case 0: break; } @@ -1958,8 +2083,8 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile) pp += 6; } - cp += toskew; - pp += fromskew; + cp += toskew; + pp += fromskew; } while (--h); } @@ -1969,57 +2094,57 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile) */ DECLAREContigPutFunc(putcontig8bitYCbCr22tile) { - uint32* cp2; - int32 incr = 2*toskew+w; - (void) y; - fromskew = (fromskew / 2) * 6; - cp2 = cp+w+toskew; - while (h>=2) { - x = w; - while (x>=2) { - uint32 Cb = pp[4]; - uint32 Cr = pp[5]; - YCbCrtoRGB(cp[0], pp[0]); - YCbCrtoRGB(cp[1], pp[1]); - YCbCrtoRGB(cp2[0], pp[2]); - YCbCrtoRGB(cp2[1], pp[3]); - cp += 2; - cp2 += 2; - pp += 6; - x -= 2; - } - if (x==1) { - uint32 Cb = pp[4]; - uint32 Cr = pp[5]; - YCbCrtoRGB(cp[0], pp[0]); - YCbCrtoRGB(cp2[0], pp[2]); - cp ++ ; - cp2 ++ ; - pp += 6; - } - cp += incr; - cp2 += incr; - pp += fromskew; - h-=2; - } - if (h==1) { - x = w; - while (x>=2) { - uint32 Cb = pp[4]; - uint32 Cr = pp[5]; - YCbCrtoRGB(cp[0], pp[0]); - YCbCrtoRGB(cp[1], pp[1]); - cp += 2; - cp2 += 2; - pp += 6; - x -= 2; - } - if (x==1) { - uint32 Cb = pp[4]; - uint32 Cr = pp[5]; - YCbCrtoRGB(cp[0], pp[0]); - } - } + uint32* cp2; + int32 incr = 2*toskew+w; + (void) y; + fromskew = (fromskew / 2) * (2*2+2); + cp2 = cp+w+toskew; + while (h>=2) { + x = w; + while (x>=2) { + uint32 Cb = pp[4]; + uint32 Cr = pp[5]; + YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp[1], pp[1]); + YCbCrtoRGB(cp2[0], pp[2]); + YCbCrtoRGB(cp2[1], pp[3]); + cp += 2; + cp2 += 2; + pp += 6; + x -= 2; + } + if (x==1) { + uint32 Cb = pp[4]; + uint32 Cr = pp[5]; + YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp2[0], pp[2]); + cp ++ ; + cp2 ++ ; + pp += 6; + } + cp += incr; + cp2 += incr; + pp += fromskew; + h-=2; + } + if (h==1) { + x = w; + while (x>=2) { + uint32 Cb = pp[4]; + uint32 Cr = pp[5]; + YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp[1], pp[1]); + cp += 2; + cp2 += 2; + pp += 6; + x -= 2; + } + if (x==1) { + uint32 Cb = pp[4]; + uint32 Cr = pp[5]; + YCbCrtoRGB(cp[0], pp[0]); + } + } } /* @@ -2027,35 +2152,36 @@ DECLAREContigPutFunc(putcontig8bitYCbCr22tile) */ DECLAREContigPutFunc(putcontig8bitYCbCr21tile) { - (void) y; - fromskew = (fromskew * 4) / 2; - do { - x = w>>1; - do { - int32 Cb = pp[2]; - int32 Cr = pp[3]; + (void) y; + fromskew = (fromskew / 2) * (2*1+2); + do { + x = w>>1; + while(x>0) { + int32 Cb = pp[2]; + int32 Cr = pp[3]; - YCbCrtoRGB(cp[0], pp[0]); - YCbCrtoRGB(cp[1], pp[1]); + YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp[1], pp[1]); - cp += 2; - pp += 4; - } while (--x); + cp += 2; + pp += 4; + x --; + } - if( (w&1) != 0 ) - { - int32 Cb = pp[2]; - int32 Cr = pp[3]; + if( (w&1) != 0 ) + { + int32 Cb = pp[2]; + int32 Cr = pp[3]; - YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp[0], pp[0]); - cp += 1; - pp += 4; - } + cp += 1; + pp += 4; + } - cp += toskew; - pp += fromskew; - } while (--h); + cp += toskew; + pp += fromskew; + } while (--h); } /* @@ -2063,37 +2189,37 @@ DECLAREContigPutFunc(putcontig8bitYCbCr21tile) */ DECLAREContigPutFunc(putcontig8bitYCbCr12tile) { - uint32* cp2; - int32 incr = 2*toskew+w; - (void) y; - fromskew = (fromskew / 2) * 4; - cp2 = cp+w+toskew; - while (h>=2) { - x = w; - do { - uint32 Cb = pp[2]; - uint32 Cr = pp[3]; - YCbCrtoRGB(cp[0], pp[0]); - YCbCrtoRGB(cp2[0], pp[1]); - cp ++; - cp2 ++; - pp += 4; - } while (--x); - cp += incr; - cp2 += incr; - pp += fromskew; - h-=2; - } - if (h==1) { - x = w; - do { - uint32 Cb = pp[2]; - uint32 Cr = pp[3]; - YCbCrtoRGB(cp[0], pp[0]); - cp ++; - pp += 4; - } while (--x); - } + uint32* cp2; + int32 incr = 2*toskew+w; + (void) y; + fromskew = (fromskew / 1) * (1 * 2 + 2); + cp2 = cp+w+toskew; + while (h>=2) { + x = w; + do { + uint32 Cb = pp[2]; + uint32 Cr = pp[3]; + YCbCrtoRGB(cp[0], pp[0]); + YCbCrtoRGB(cp2[0], pp[1]); + cp ++; + cp2 ++; + pp += 4; + } while (--x); + cp += incr; + cp2 += incr; + pp += fromskew; + h-=2; + } + if (h==1) { + x = w; + do { + uint32 Cb = pp[2]; + uint32 Cr = pp[3]; + YCbCrtoRGB(cp[0], pp[0]); + cp ++; + pp += 4; + } while (--x); + } } /* @@ -2101,21 +2227,21 @@ DECLAREContigPutFunc(putcontig8bitYCbCr12tile) */ DECLAREContigPutFunc(putcontig8bitYCbCr11tile) { - (void) y; - fromskew *= 3; - do { - x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */ - do { - int32 Cb = pp[1]; - int32 Cr = pp[2]; + (void) y; + fromskew = (fromskew / 1) * (1 * 1 + 2); + do { + x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */ + do { + int32 Cb = pp[1]; + int32 Cr = pp[2]; - YCbCrtoRGB(*cp++, pp[0]); + YCbCrtoRGB(*cp++, pp[0]); - pp += 3; - } while (--x); - cp += toskew; - pp += fromskew; - } while (--h); + pp += 3; + } while (--x); + cp += toskew; + pp += fromskew; + } while (--h); } /* @@ -2123,82 +2249,118 @@ DECLAREContigPutFunc(putcontig8bitYCbCr11tile) */ DECLARESepPutFunc(putseparate8bitYCbCr11tile) { - (void) y; - (void) a; - /* TODO: naming of input vars is still off, change obfuscating declaration inside define, or resolve obfuscation */ - while (h-- > 0) { - x = w; - do { - uint32 dr, dg, db; - TIFFYCbCrtoRGB(img->ycbcr,*r++,*g++,*b++,&dr,&dg,&db); - *cp++ = PACK(dr,dg,db); - } while (--x); - SKEW(r, g, b, fromskew); - cp += toskew; - } + (void) y; + (void) a; + /* TODO: naming of input vars is still off, change obfuscating declaration inside define, or resolve obfuscation */ + for( ; h > 0; --h) { + x = w; + do { + uint32 dr, dg, db; + TIFFYCbCrtoRGB(img->ycbcr,*r++,*g++,*b++,&dr,&dg,&db); + *cp++ = PACK(dr,dg,db); + } while (--x); + SKEW(r, g, b, fromskew); + cp += toskew; + } } #undef YCbCrtoRGB +static int isInRefBlackWhiteRange(float f) +{ + return f > (float)(-0x7FFFFFFF + 128) && f < (float)0x7FFFFFFF; +} + static int initYCbCrConversion(TIFFRGBAImage* img) { - static const char module[] = "initYCbCrConversion"; + static const char module[] = "initYCbCrConversion"; - float *luma, *refBlackWhite; + float *luma, *refBlackWhite; - if (img->ycbcr == NULL) { - img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc( - TIFFroundup_32(sizeof (TIFFYCbCrToRGB), sizeof (long)) - + 4*256*sizeof (TIFFRGBValue) - + 2*256*sizeof (int) - + 3*256*sizeof (int32) - ); - if (img->ycbcr == NULL) { + if (img->ycbcr == NULL) { + img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc( + TIFFroundup_32(sizeof (TIFFYCbCrToRGB), sizeof (long)) + + 4*256*sizeof (TIFFRGBValue) + + 2*256*sizeof (int) + + 3*256*sizeof (int32) + ); + if (img->ycbcr == NULL) { + TIFFErrorExt(img->tif->tif_clientdata, module, + "No space for YCbCr->RGB conversion state"); + return (0); + } + } + + TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma); + TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE, + &refBlackWhite); + + /* Do some validation to avoid later issues. Detect NaN for now */ + /* and also if lumaGreen is zero since we divide by it later */ + if( luma[0] != luma[0] || + luma[1] != luma[1] || + luma[1] == 0.0 || + luma[2] != luma[2] ) + { TIFFErrorExt(img->tif->tif_clientdata, module, - "No space for YCbCr->RGB conversion state"); + "Invalid values for YCbCrCoefficients tag"); return (0); } - } - TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma); - TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE, - &refBlackWhite); - if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0) - return(0); - return (1); + if( !isInRefBlackWhiteRange(refBlackWhite[0]) || + !isInRefBlackWhiteRange(refBlackWhite[1]) || + !isInRefBlackWhiteRange(refBlackWhite[2]) || + !isInRefBlackWhiteRange(refBlackWhite[3]) || + !isInRefBlackWhiteRange(refBlackWhite[4]) || + !isInRefBlackWhiteRange(refBlackWhite[5]) ) + { + TIFFErrorExt(img->tif->tif_clientdata, module, + "Invalid values for ReferenceBlackWhite tag"); + return (0); + } + + if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0) + return(0); + return (1); } static tileContigRoutine initCIELabConversion(TIFFRGBAImage* img) { - static const char module[] = "initCIELabConversion"; + static const char module[] = "initCIELabConversion"; - float *whitePoint; - float refWhite[3]; + float *whitePoint; + float refWhite[3]; - if (!img->cielab) { - img->cielab = (TIFFCIELabToRGB *) - _TIFFmalloc(sizeof(TIFFCIELabToRGB)); - if (!img->cielab) { - TIFFErrorExt(img->tif->tif_clientdata, module, - "No space for CIE L*a*b*->RGB conversion state."); - return NULL; + TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint); + if (whitePoint[1] == 0.0f ) { + TIFFErrorExt(img->tif->tif_clientdata, module, + "Invalid value for WhitePoint tag."); + return NULL; } - } - TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint); - refWhite[1] = 100.0F; - refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1]; - refWhite[2] = (1.0F - whitePoint[0] - whitePoint[1]) - / whitePoint[1] * refWhite[1]; - if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0) { - TIFFErrorExt(img->tif->tif_clientdata, module, - "Failed to initialize CIE L*a*b*->RGB conversion state."); - _TIFFfree(img->cielab); - return NULL; - } + if (!img->cielab) { + img->cielab = (TIFFCIELabToRGB *) + _TIFFmalloc(sizeof(TIFFCIELabToRGB)); + if (!img->cielab) { + TIFFErrorExt(img->tif->tif_clientdata, module, + "No space for CIE L*a*b*->RGB conversion state."); + return NULL; + } + } - return putcontig8bitCIELab; + refWhite[1] = 100.0F; + refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1]; + refWhite[2] = (1.0F - whitePoint[0] - whitePoint[1]) + / whitePoint[1] * refWhite[1]; + if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0) { + TIFFErrorExt(img->tif->tif_clientdata, module, + "Failed to initialize CIE L*a*b*->RGB conversion state."); + _TIFFfree(img->cielab); + return NULL; + } + + return putcontig8bitCIELab; } /* @@ -2221,42 +2383,42 @@ makebwmap(TIFFRGBAImage* img) nsamples = 1; img->BWmap = (uint32**) _TIFFmalloc( - 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); + 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); if (img->BWmap == NULL) { - TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for B&W mapping table"); - return (0); + TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for B&W mapping table"); + return (0); } p = (uint32*)(img->BWmap + 256); for (i = 0; i < 256; i++) { - TIFFRGBValue c; - img->BWmap[i] = p; - switch (bitspersample) { + TIFFRGBValue c; + img->BWmap[i] = p; + switch (bitspersample) { #define GREY(x) c = Map[x]; *p++ = PACK(c,c,c); - case 1: - GREY(i>>7); - GREY((i>>6)&1); - GREY((i>>5)&1); - GREY((i>>4)&1); - GREY((i>>3)&1); - GREY((i>>2)&1); - GREY((i>>1)&1); - GREY(i&1); - break; - case 2: - GREY(i>>6); - GREY((i>>4)&3); - GREY((i>>2)&3); - GREY(i&3); - break; - case 4: - GREY(i>>4); - GREY(i&0xf); - break; - case 8: + case 1: + GREY(i>>7); + GREY((i>>6)&1); + GREY((i>>5)&1); + GREY((i>>4)&1); + GREY((i>>3)&1); + GREY((i>>2)&1); + GREY((i>>1)&1); + GREY(i&1); + break; + case 2: + GREY(i>>6); + GREY((i>>4)&3); + GREY((i>>2)&3); + GREY(i&3); + break; + case 4: + GREY(i>>4); + GREY(i&0xf); + break; + case 8: case 16: - GREY(i); - break; - } + GREY(i); + break; + } #undef GREY } return (1); @@ -2266,42 +2428,43 @@ makebwmap(TIFFRGBAImage* img) * Construct a mapping table to convert from the range * of the data samples to [0,255] --for display. This * process also handles inverting B&W images when needed. - */ + */ static int setupMap(TIFFRGBAImage* img) { int32 x, range; range = (int32)((1L<bitspersample)-1); - + /* treat 16 bit the same as eight bit */ if( img->bitspersample == 16 ) range = (int32) 255; img->Map = (TIFFRGBValue*) _TIFFmalloc((range+1) * sizeof (TIFFRGBValue)); if (img->Map == NULL) { - TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), - "No space for photometric conversion table"); - return (0); + TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), + "No space for photometric conversion table"); + return (0); } if (img->photometric == PHOTOMETRIC_MINISWHITE) { - for (x = 0; x <= range; x++) - img->Map[x] = (TIFFRGBValue) (((range - x) * 255) / range); + for (x = 0; x <= range; x++) + img->Map[x] = (TIFFRGBValue) (((range - x) * 255) / range); } else { - for (x = 0; x <= range; x++) - img->Map[x] = (TIFFRGBValue) ((x * 255) / range); + for (x = 0; x <= range; x++) + img->Map[x] = (TIFFRGBValue) ((x * 255) / range); } if (img->bitspersample <= 16 && - (img->photometric == PHOTOMETRIC_MINISBLACK || - img->photometric == PHOTOMETRIC_MINISWHITE)) { - /* - * Use photometric mapping table to construct - * unpacking tables for samples <= 8 bits. - */ - if (!makebwmap(img)) - return (0); - /* no longer need Map, free it */ - _TIFFfree(img->Map), img->Map = NULL; + (img->photometric == PHOTOMETRIC_MINISBLACK || + img->photometric == PHOTOMETRIC_MINISWHITE)) { + /* + * Use photometric mapping table to construct + * unpacking tables for samples <= 8 bits. + */ + if (!makebwmap(img)) + return (0); + /* no longer need Map, free it */ + _TIFFfree(img->Map); + img->Map = NULL; } return (1); } @@ -2315,8 +2478,8 @@ checkcmap(TIFFRGBAImage* img) long n = 1L<bitspersample; while (n-- > 0) - if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) - return (16); + if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) + return (16); return (8); } @@ -2330,9 +2493,9 @@ cvtcmap(TIFFRGBAImage* img) for (i = (1L<bitspersample)-1; i >= 0; i--) { #define CVT(x) ((uint16)((x)>>8)) - r[i] = CVT(r[i]); - g[i] = CVT(g[i]); - b[i] = CVT(b[i]); + r[i] = CVT(r[i]); + g[i] = CVT(g[i]); + b[i] = CVT(b[i]); #undef CVT } } @@ -2356,47 +2519,47 @@ makecmap(TIFFRGBAImage* img) int i; img->PALmap = (uint32**) _TIFFmalloc( - 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); + 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); if (img->PALmap == NULL) { - TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for Palette mapping table"); - return (0); - } + TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for Palette mapping table"); + return (0); + } p = (uint32*)(img->PALmap + 256); for (i = 0; i < 256; i++) { - TIFFRGBValue c; - img->PALmap[i] = p; + TIFFRGBValue c; + img->PALmap[i] = p; #define CMAP(x) c = (TIFFRGBValue) x; *p++ = PACK(r[c]&0xff, g[c]&0xff, b[c]&0xff); - switch (bitspersample) { - case 1: - CMAP(i>>7); - CMAP((i>>6)&1); - CMAP((i>>5)&1); - CMAP((i>>4)&1); - CMAP((i>>3)&1); - CMAP((i>>2)&1); - CMAP((i>>1)&1); - CMAP(i&1); - break; - case 2: - CMAP(i>>6); - CMAP((i>>4)&3); - CMAP((i>>2)&3); - CMAP(i&3); - break; - case 4: - CMAP(i>>4); - CMAP(i&0xf); - break; - case 8: - CMAP(i); - break; - } + switch (bitspersample) { + case 1: + CMAP(i>>7); + CMAP((i>>6)&1); + CMAP((i>>5)&1); + CMAP((i>>4)&1); + CMAP((i>>3)&1); + CMAP((i>>2)&1); + CMAP((i>>1)&1); + CMAP(i&1); + break; + case 2: + CMAP(i>>6); + CMAP((i>>4)&3); + CMAP((i>>2)&3); + CMAP(i&3); + break; + case 4: + CMAP(i>>4); + CMAP(i&0xf); + break; + case 8: + CMAP(i); + break; + } #undef CMAP } return (1); } -/* +/* * Construct any mapping table used * by the associated put routine. */ @@ -2407,30 +2570,30 @@ buildMap(TIFFRGBAImage* img) case PHOTOMETRIC_RGB: case PHOTOMETRIC_YCBCR: case PHOTOMETRIC_SEPARATED: - if (img->bitspersample == 8) - break; - /* fall thru... */ + if (img->bitspersample == 8) + break; + /* fall through... */ case PHOTOMETRIC_MINISBLACK: case PHOTOMETRIC_MINISWHITE: - if (!setupMap(img)) - return (0); - break; + if (!setupMap(img)) + return (0); + break; case PHOTOMETRIC_PALETTE: - /* - * Convert 16-bit colormap to 8-bit (unless it looks - * like an old-style 8-bit colormap). - */ - if (checkcmap(img) == 16) - cvtcmap(img); - else - TIFFWarningExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "Assuming 8-bit colormap"); - /* - * Use mapping table and colormap to construct - * unpacking tables for samples < 8 bits. - */ - if (img->bitspersample <= 8 && !makecmap(img)) - return (0); - break; + /* + * Convert 16-bit colormap to 8-bit (unless it looks + * like an old-style 8-bit colormap). + */ + if (checkcmap(img) == 16) + cvtcmap(img); + else + TIFFWarningExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "Assuming 8-bit colormap"); + /* + * Use mapping table and colormap to construct + * unpacking tables for samples < 8 bits. + */ + if (img->bitspersample <= 8 && !makecmap(img)) + return (0); + break; } return (1); } @@ -2441,146 +2604,150 @@ buildMap(TIFFRGBAImage* img) static int PickContigCase(TIFFRGBAImage* img) { - img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig; - img->put.contig = NULL; - switch (img->photometric) { - case PHOTOMETRIC_RGB: - switch (img->bitspersample) { - case 8: - if (img->alpha == EXTRASAMPLE_ASSOCALPHA) - img->put.contig = putRGBAAcontig8bittile; - else if (img->alpha == EXTRASAMPLE_UNASSALPHA) - { - if (BuildMapUaToAa(img)) - img->put.contig = putRGBUAcontig8bittile; - } - else - img->put.contig = putRGBcontig8bittile; - break; - case 16: - if (img->alpha == EXTRASAMPLE_ASSOCALPHA) - { - if (BuildMapBitdepth16To8(img)) - img->put.contig = putRGBAAcontig16bittile; - } - else if (img->alpha == EXTRASAMPLE_UNASSALPHA) - { - if (BuildMapBitdepth16To8(img) && - BuildMapUaToAa(img)) - img->put.contig = putRGBUAcontig16bittile; - } - else - { - if (BuildMapBitdepth16To8(img)) - img->put.contig = putRGBcontig16bittile; - } - break; - } - break; - case PHOTOMETRIC_SEPARATED: - if (buildMap(img)) { - if (img->bitspersample == 8) { - if (!img->Map) - img->put.contig = putRGBcontig8bitCMYKtile; - else - img->put.contig = putRGBcontig8bitCMYKMaptile; - } - } - break; - case PHOTOMETRIC_PALETTE: - if (buildMap(img)) { - switch (img->bitspersample) { - case 8: - img->put.contig = put8bitcmaptile; - break; - case 4: - img->put.contig = put4bitcmaptile; - break; - case 2: - img->put.contig = put2bitcmaptile; - break; - case 1: - img->put.contig = put1bitcmaptile; - break; - } - } - break; - case PHOTOMETRIC_MINISWHITE: - case PHOTOMETRIC_MINISBLACK: - if (buildMap(img)) { - switch (img->bitspersample) { - case 16: - img->put.contig = put16bitbwtile; - break; - case 8: - if (img->alpha && img->samplesperpixel == 2) - img->put.contig = putagreytile; - else - img->put.contig = putgreytile; - break; - case 4: - img->put.contig = put4bitbwtile; - break; - case 2: - img->put.contig = put2bitbwtile; - break; - case 1: - img->put.contig = put1bitbwtile; - break; - } - } - break; - case PHOTOMETRIC_YCBCR: - if ((img->bitspersample==8) && (img->samplesperpixel==3)) - { - if (initYCbCrConversion(img)!=0) - { - /* - * The 6.0 spec says that subsampling must be - * one of 1, 2, or 4, and that vertical subsampling - * must always be <= horizontal subsampling; so - * there are only a few possibilities and we just - * enumerate the cases. - * Joris: added support for the [1,2] case, nonetheless, to accomodate - * some OJPEG files - */ - uint16 SubsamplingHor; - uint16 SubsamplingVer; - TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &SubsamplingHor, &SubsamplingVer); - switch ((SubsamplingHor<<4)|SubsamplingVer) { - case 0x44: - img->put.contig = putcontig8bitYCbCr44tile; - break; - case 0x42: - img->put.contig = putcontig8bitYCbCr42tile; - break; - case 0x41: - img->put.contig = putcontig8bitYCbCr41tile; - break; - case 0x22: - img->put.contig = putcontig8bitYCbCr22tile; - break; - case 0x21: - img->put.contig = putcontig8bitYCbCr21tile; - break; - case 0x12: - img->put.contig = putcontig8bitYCbCr12tile; - break; - case 0x11: - img->put.contig = putcontig8bitYCbCr11tile; - break; - } - } - } - break; - case PHOTOMETRIC_CIELAB: - if (buildMap(img)) { - if (img->bitspersample == 8) - img->put.contig = initCIELabConversion(img); - break; - } - } - return ((img->get!=NULL) && (img->put.contig!=NULL)); + img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig; + img->put.contig = NULL; + switch (img->photometric) { + case PHOTOMETRIC_RGB: + switch (img->bitspersample) { + case 8: + if (img->alpha == EXTRASAMPLE_ASSOCALPHA && + img->samplesperpixel >= 4) + img->put.contig = putRGBAAcontig8bittile; + else if (img->alpha == EXTRASAMPLE_UNASSALPHA && + img->samplesperpixel >= 4) + { + if (BuildMapUaToAa(img)) + img->put.contig = putRGBUAcontig8bittile; + } + else if( img->samplesperpixel >= 3 ) + img->put.contig = putRGBcontig8bittile; + break; + case 16: + if (img->alpha == EXTRASAMPLE_ASSOCALPHA && + img->samplesperpixel >=4 ) + { + if (BuildMapBitdepth16To8(img)) + img->put.contig = putRGBAAcontig16bittile; + } + else if (img->alpha == EXTRASAMPLE_UNASSALPHA && + img->samplesperpixel >=4 ) + { + if (BuildMapBitdepth16To8(img) && + BuildMapUaToAa(img)) + img->put.contig = putRGBUAcontig16bittile; + } + else if( img->samplesperpixel >=3 ) + { + if (BuildMapBitdepth16To8(img)) + img->put.contig = putRGBcontig16bittile; + } + break; + } + break; + case PHOTOMETRIC_SEPARATED: + if (img->samplesperpixel >=4 && buildMap(img)) { + if (img->bitspersample == 8) { + if (!img->Map) + img->put.contig = putRGBcontig8bitCMYKtile; + else + img->put.contig = putRGBcontig8bitCMYKMaptile; + } + } + break; + case PHOTOMETRIC_PALETTE: + if (buildMap(img)) { + switch (img->bitspersample) { + case 8: + img->put.contig = put8bitcmaptile; + break; + case 4: + img->put.contig = put4bitcmaptile; + break; + case 2: + img->put.contig = put2bitcmaptile; + break; + case 1: + img->put.contig = put1bitcmaptile; + break; + } + } + break; + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + if (buildMap(img)) { + switch (img->bitspersample) { + case 16: + img->put.contig = put16bitbwtile; + break; + case 8: + if (img->alpha && img->samplesperpixel == 2) + img->put.contig = putagreytile; + else + img->put.contig = putgreytile; + break; + case 4: + img->put.contig = put4bitbwtile; + break; + case 2: + img->put.contig = put2bitbwtile; + break; + case 1: + img->put.contig = put1bitbwtile; + break; + } + } + break; + case PHOTOMETRIC_YCBCR: + if ((img->bitspersample==8) && (img->samplesperpixel==3)) + { + if (initYCbCrConversion(img)!=0) + { + /* + * The 6.0 spec says that subsampling must be + * one of 1, 2, or 4, and that vertical subsampling + * must always be <= horizontal subsampling; so + * there are only a few possibilities and we just + * enumerate the cases. + * Joris: added support for the [1,2] case, nonetheless, to accommodate + * some OJPEG files + */ + uint16 SubsamplingHor; + uint16 SubsamplingVer; + TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &SubsamplingHor, &SubsamplingVer); + switch ((SubsamplingHor<<4)|SubsamplingVer) { + case 0x44: + img->put.contig = putcontig8bitYCbCr44tile; + break; + case 0x42: + img->put.contig = putcontig8bitYCbCr42tile; + break; + case 0x41: + img->put.contig = putcontig8bitYCbCr41tile; + break; + case 0x22: + img->put.contig = putcontig8bitYCbCr22tile; + break; + case 0x21: + img->put.contig = putcontig8bitYCbCr21tile; + break; + case 0x12: + img->put.contig = putcontig8bitYCbCr12tile; + break; + case 0x11: + img->put.contig = putcontig8bitYCbCr11tile; + break; + } + } + } + break; + case PHOTOMETRIC_CIELAB: + if (img->samplesperpixel == 3 && buildMap(img)) { + if (img->bitspersample == 8) + img->put.contig = initCIELabConversion(img); + break; + } + } + return ((img->get!=NULL) && (img->put.contig!=NULL)); } /* @@ -2592,111 +2759,111 @@ PickContigCase(TIFFRGBAImage* img) static int PickSeparateCase(TIFFRGBAImage* img) { - img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate; - img->put.separate = NULL; - switch (img->photometric) { - case PHOTOMETRIC_MINISWHITE: - case PHOTOMETRIC_MINISBLACK: - /* greyscale images processed pretty much as RGB by gtTileSeparate */ - case PHOTOMETRIC_RGB: - switch (img->bitspersample) { - case 8: - if (img->alpha == EXTRASAMPLE_ASSOCALPHA) - img->put.separate = putRGBAAseparate8bittile; - else if (img->alpha == EXTRASAMPLE_UNASSALPHA) - { - if (BuildMapUaToAa(img)) - img->put.separate = putRGBUAseparate8bittile; - } - else - img->put.separate = putRGBseparate8bittile; - break; - case 16: - if (img->alpha == EXTRASAMPLE_ASSOCALPHA) - { - if (BuildMapBitdepth16To8(img)) - img->put.separate = putRGBAAseparate16bittile; - } - else if (img->alpha == EXTRASAMPLE_UNASSALPHA) - { - if (BuildMapBitdepth16To8(img) && - BuildMapUaToAa(img)) - img->put.separate = putRGBUAseparate16bittile; - } - else - { - if (BuildMapBitdepth16To8(img)) - img->put.separate = putRGBseparate16bittile; - } - break; - } - break; - case PHOTOMETRIC_SEPARATED: - if (img->bitspersample == 8 && img->samplesperpixel == 4) - { - img->alpha = 1; // Not alpha, but seems like the only way to get 4th band - img->put.separate = putCMYKseparate8bittile; - } - break; - case PHOTOMETRIC_YCBCR: - if ((img->bitspersample==8) && (img->samplesperpixel==3)) - { - if (initYCbCrConversion(img)!=0) - { - uint16 hs, vs; - TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs); - switch ((hs<<4)|vs) { - case 0x11: - img->put.separate = putseparate8bitYCbCr11tile; - break; - /* TODO: add other cases here */ - } - } - } - break; - } - return ((img->get!=NULL) && (img->put.separate!=NULL)); + img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate; + img->put.separate = NULL; + switch (img->photometric) { + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + /* greyscale images processed pretty much as RGB by gtTileSeparate */ + case PHOTOMETRIC_RGB: + switch (img->bitspersample) { + case 8: + if (img->alpha == EXTRASAMPLE_ASSOCALPHA) + img->put.separate = putRGBAAseparate8bittile; + else if (img->alpha == EXTRASAMPLE_UNASSALPHA) + { + if (BuildMapUaToAa(img)) + img->put.separate = putRGBUAseparate8bittile; + } + else + img->put.separate = putRGBseparate8bittile; + break; + case 16: + if (img->alpha == EXTRASAMPLE_ASSOCALPHA) + { + if (BuildMapBitdepth16To8(img)) + img->put.separate = putRGBAAseparate16bittile; + } + else if (img->alpha == EXTRASAMPLE_UNASSALPHA) + { + if (BuildMapBitdepth16To8(img) && + BuildMapUaToAa(img)) + img->put.separate = putRGBUAseparate16bittile; + } + else + { + if (BuildMapBitdepth16To8(img)) + img->put.separate = putRGBseparate16bittile; + } + break; + } + break; + case PHOTOMETRIC_SEPARATED: + if (img->bitspersample == 8 && img->samplesperpixel == 4) + { + img->alpha = 1; // Not alpha, but seems like the only way to get 4th band + img->put.separate = putCMYKseparate8bittile; + } + break; + case PHOTOMETRIC_YCBCR: + if ((img->bitspersample==8) && (img->samplesperpixel==3)) + { + if (initYCbCrConversion(img)!=0) + { + uint16 hs, vs; + TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs); + switch ((hs<<4)|vs) { + case 0x11: + img->put.separate = putseparate8bitYCbCr11tile; + break; + /* TODO: add other cases here */ + } + } + } + break; + } + return ((img->get!=NULL) && (img->put.separate!=NULL)); } static int BuildMapUaToAa(TIFFRGBAImage* img) { - static const char module[]="BuildMapUaToAa"; - uint8* m; - uint16 na,nv; - assert(img->UaToAa==NULL); - img->UaToAa=_TIFFmalloc(65536); - if (img->UaToAa==NULL) - { - TIFFErrorExt(img->tif->tif_clientdata,module,"Out of memory"); - return(0); - } - m=img->UaToAa; - for (na=0; na<256; na++) - { - for (nv=0; nv<256; nv++) - *m++=(nv*na+127)/255; - } - return(1); + static const char module[]="BuildMapUaToAa"; + uint8* m; + uint16 na,nv; + assert(img->UaToAa==NULL); + img->UaToAa=_TIFFmalloc(65536); + if (img->UaToAa==NULL) + { + TIFFErrorExt(img->tif->tif_clientdata,module,"Out of memory"); + return(0); + } + m=img->UaToAa; + for (na=0; na<256; na++) + { + for (nv=0; nv<256; nv++) + *m++=(uint8)((nv*na+127)/255); + } + return(1); } static int BuildMapBitdepth16To8(TIFFRGBAImage* img) { - static const char module[]="BuildMapBitdepth16To8"; - uint8* m; - uint32 n; - assert(img->Bitdepth16To8==NULL); - img->Bitdepth16To8=_TIFFmalloc(65536); - if (img->Bitdepth16To8==NULL) - { - TIFFErrorExt(img->tif->tif_clientdata,module,"Out of memory"); - return(0); - } - m=img->Bitdepth16To8; - for (n=0; n<65536; n++) - *m++=(n+128)/257; - return(1); + static const char module[]="BuildMapBitdepth16To8"; + uint8* m; + uint32 n; + assert(img->Bitdepth16To8==NULL); + img->Bitdepth16To8=_TIFFmalloc(65536); + if (img->Bitdepth16To8==NULL) + { + TIFFErrorExt(img->tif->tif_clientdata,module,"Out of memory"); + return(0); + } + m=img->Bitdepth16To8; + for (n=0; n<65536; n++) + *m++=(uint8)((n+128)/257); + return(1); } @@ -2711,6 +2878,13 @@ BuildMapBitdepth16To8(TIFFRGBAImage* img) int TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster ) +{ + return TIFFReadRGBAStripExt(tif, row, raster, 0 ); +} + +int +TIFFReadRGBAStripExt(TIFF* tif, uint32 row, uint32 * raster, int stop_on_error) + { char emsg[1024] = ""; TIFFRGBAImage img; @@ -2719,20 +2893,20 @@ TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster ) if( TIFFIsTiled( tif ) ) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Can't use TIFFReadRGBAStrip() with tiled file."); - return (0); + return (0); } - + TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); if( (row % rowsperstrip) != 0 ) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), - "Row passed to TIFFReadRGBAStrip() must be first in a strip."); - return (0); + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), + "Row passed to TIFFReadRGBAStrip() must be first in a strip."); + return (0); } - if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, 0, emsg)) { + if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg)) { img.row_offset = row; img.col_offset = 0; @@ -2741,15 +2915,15 @@ TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster ) rows_to_read = img.height - row; else rows_to_read = rowsperstrip; - - ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read ); - - TIFFRGBAImageEnd(&img); + + ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read ); + + TIFFRGBAImageEnd(&img); } else { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); - ok = 0; + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); + ok = 0; } - + return (ok); } @@ -2762,6 +2936,13 @@ TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster ) int TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster) +{ + return TIFFReadRGBATileExt(tif, col, row, raster, 0 ); +} + + +int +TIFFReadRGBATileExt(TIFF* tif, uint32 col, uint32 row, uint32 * raster, int stop_on_error ) { char emsg[1024] = ""; TIFFRGBAImage img; @@ -2774,32 +2955,32 @@ TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster) * Verify that our request is legal - on a tile file, and on a * tile boundary. */ - + if( !TIFFIsTiled( tif ) ) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), - "Can't use TIFFReadRGBATile() with stripped file."); - return (0); + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), + "Can't use TIFFReadRGBATile() with stripped file."); + return (0); } - + TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize); TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize); if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 ) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Row/col passed to TIFFReadRGBATile() must be top" "left corner of a tile."); - return (0); + return (0); } /* * Setup the RGBA reader. */ - - if (!TIFFRGBAImageOK(tif, emsg) - || !TIFFRGBAImageBegin(&img, tif, 0, emsg)) { - TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); - return( 0 ); + + if (!TIFFRGBAImageOK(tif, emsg) + || !TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg)) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); + return( 0 ); } /* @@ -2813,7 +2994,7 @@ TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster) read_ysize = img.height - row; else read_ysize = tile_ysize; - + if( col + tile_xsize > img.width ) read_xsize = img.width - col; else @@ -2822,12 +3003,12 @@ TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster) /* * Read the chunk of imagery. */ - + img.row_offset = row; img.col_offset = col; ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize ); - + TIFFRGBAImageEnd(&img); /* @@ -2835,7 +3016,7 @@ TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster) * shifting the data around as if a full tile of data is being returned. * * This is all the more complicated because the image is organized in - * bottom to top format. + * bottom to top format. */ if( read_xsize == tile_xsize && read_ysize == tile_ysize ) diff --git a/3rdparty/libtiff/tif_jbig.c b/3rdparty/libtiff/tif_jbig.c index ab29e558a3..7a14dd9ab0 100644 --- a/3rdparty/libtiff/tif_jbig.c +++ b/3rdparty/libtiff/tif_jbig.c @@ -1,4 +1,4 @@ -/* $Id: tif_jbig.c,v 1.15 2010-03-10 18:56:48 bfriesen Exp $ */ +/* $Id: tif_jbig.c,v 1.16 2017-06-26 15:20:00 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -39,165 +39,166 @@ static int JBIGSetupDecode(TIFF* tif) { - if (TIFFNumberOfStrips(tif) != 1) - { - TIFFErrorExt(tif->tif_clientdata, "JBIG", "Multistrip images not supported in decoder"); - return 0; - } + if (TIFFNumberOfStrips(tif) != 1) + { + TIFFErrorExt(tif->tif_clientdata, "JBIG", "Multistrip images not supported in decoder"); + return 0; + } - return 1; + return 1; } static int JBIGDecode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s) { - struct jbg_dec_state decoder; - int decodeStatus = 0; - unsigned char* pImage = NULL; - (void) size, (void) s; + struct jbg_dec_state decoder; + int decodeStatus = 0; + unsigned char* pImage = NULL; + (void) size, (void) s; - if (isFillOrder(tif, tif->tif_dir.td_fillorder)) - { - TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize); - } + if (isFillOrder(tif, tif->tif_dir.td_fillorder)) + { + TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize); + } - jbg_dec_init(&decoder); + jbg_dec_init(&decoder); #if defined(HAVE_JBG_NEWLEN) - jbg_newlen(tif->tif_rawdata, (size_t)tif->tif_rawdatasize); - /* - * I do not check the return status of jbg_newlen because even if this - * function fails it does not necessarily mean that decoding the image - * will fail. It is generally only needed for received fax images - * that do not contain the actual length of the image in the BIE - * header. I do not log when an error occurs because that will cause - * problems when converting JBIG encoded TIFF's to - * PostScript. As long as the actual image length is contained in the - * BIE header jbg_dec_in should succeed. - */ + jbg_newlen(tif->tif_rawdata, (size_t)tif->tif_rawdatasize); + /* + * I do not check the return status of jbg_newlen because even if this + * function fails it does not necessarily mean that decoding the image + * will fail. It is generally only needed for received fax images + * that do not contain the actual length of the image in the BIE + * header. I do not log when an error occurs because that will cause + * problems when converting JBIG encoded TIFF's to + * PostScript. As long as the actual image length is contained in the + * BIE header jbg_dec_in should succeed. + */ #endif /* HAVE_JBG_NEWLEN */ - decodeStatus = jbg_dec_in(&decoder, (unsigned char*)tif->tif_rawdata, - (size_t)tif->tif_rawdatasize, NULL); - if (JBG_EOK != decodeStatus) - { - /* - * XXX: JBG_EN constant was defined in pre-2.0 releases of the - * JBIG-KIT. Since the 2.0 the error reporting functions were - * changed. We will handle both cases here. - */ - TIFFErrorExt(tif->tif_clientdata, - "JBIG", "Error (%d) decoding: %s", - decodeStatus, + decodeStatus = jbg_dec_in(&decoder, (unsigned char*)tif->tif_rawdata, + (size_t)tif->tif_rawdatasize, NULL); + if (JBG_EOK != decodeStatus) + { + /* + * XXX: JBG_EN constant was defined in pre-2.0 releases of the + * JBIG-KIT. Since the 2.0 the error reporting functions were + * changed. We will handle both cases here. + */ + TIFFErrorExt(tif->tif_clientdata, + "JBIG", "Error (%d) decoding: %s", + decodeStatus, #if defined(JBG_EN) - jbg_strerror(decodeStatus, JBG_EN) + jbg_strerror(decodeStatus, JBG_EN) #else - jbg_strerror(decodeStatus) + jbg_strerror(decodeStatus) #endif - ); - return 0; - } + ); + jbg_dec_free(&decoder); + return 0; + } - pImage = jbg_dec_getimage(&decoder, 0); - _TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder)); - jbg_dec_free(&decoder); - return 1; + pImage = jbg_dec_getimage(&decoder, 0); + _TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder)); + jbg_dec_free(&decoder); + return 1; } static int JBIGSetupEncode(TIFF* tif) { - if (TIFFNumberOfStrips(tif) != 1) - { - TIFFErrorExt(tif->tif_clientdata, "JBIG", "Multistrip images not supported in encoder"); - return 0; - } + if (TIFFNumberOfStrips(tif) != 1) + { + TIFFErrorExt(tif->tif_clientdata, "JBIG", "Multistrip images not supported in encoder"); + return 0; + } - return 1; + return 1; } static int JBIGCopyEncodedData(TIFF* tif, unsigned char* pp, size_t cc, uint16 s) { - (void) s; - while (cc > 0) - { - tmsize_t n = (tmsize_t)cc; + (void) s; + while (cc > 0) + { + tmsize_t n = (tmsize_t)cc; - if (tif->tif_rawcc + n > tif->tif_rawdatasize) - { - n = tif->tif_rawdatasize - tif->tif_rawcc; - } + if (tif->tif_rawcc + n > tif->tif_rawdatasize) + { + n = tif->tif_rawdatasize - tif->tif_rawcc; + } - assert(n > 0); - _TIFFmemcpy(tif->tif_rawcp, pp, n); - tif->tif_rawcp += n; - tif->tif_rawcc += n; - pp += n; - cc -= (size_t)n; - if (tif->tif_rawcc >= tif->tif_rawdatasize && - !TIFFFlushData1(tif)) - { - return (-1); - } - } + assert(n > 0); + _TIFFmemcpy(tif->tif_rawcp, pp, n); + tif->tif_rawcp += n; + tif->tif_rawcc += n; + pp += n; + cc -= (size_t)n; + if (tif->tif_rawcc >= tif->tif_rawdatasize && + !TIFFFlushData1(tif)) + { + return (-1); + } + } - return (1); + return (1); } static void JBIGOutputBie(unsigned char* buffer, size_t len, void* userData) { - TIFF* tif = (TIFF*)userData; + TIFF* tif = (TIFF*)userData; - if (isFillOrder(tif, tif->tif_dir.td_fillorder)) - { - TIFFReverseBits(buffer, (tmsize_t)len); - } + if (isFillOrder(tif, tif->tif_dir.td_fillorder)) + { + TIFFReverseBits(buffer, (tmsize_t)len); + } - JBIGCopyEncodedData(tif, buffer, len, 0); + JBIGCopyEncodedData(tif, buffer, len, 0); } static int JBIGEncode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s) { - TIFFDirectory* dir = &tif->tif_dir; - struct jbg_enc_state encoder; + TIFFDirectory* dir = &tif->tif_dir; + struct jbg_enc_state encoder; - (void) size, (void) s; + (void) size, (void) s; - jbg_enc_init(&encoder, - dir->td_imagewidth, - dir->td_imagelength, - 1, - &buffer, - JBIGOutputBie, - tif); - /* - * jbg_enc_out does the "real" encoding. As data is encoded, - * JBIGOutputBie is called, which writes the data to the directory. - */ - jbg_enc_out(&encoder); - jbg_enc_free(&encoder); + jbg_enc_init(&encoder, + dir->td_imagewidth, + dir->td_imagelength, + 1, + &buffer, + JBIGOutputBie, + tif); + /* + * jbg_enc_out does the "real" encoding. As data is encoded, + * JBIGOutputBie is called, which writes the data to the directory. + */ + jbg_enc_out(&encoder); + jbg_enc_free(&encoder); - return 1; + return 1; } int TIFFInitJBIG(TIFF* tif, int scheme) { - assert(scheme == COMPRESSION_JBIG); + assert(scheme == COMPRESSION_JBIG); - /* - * These flags are set so the JBIG Codec can control when to reverse - * bits and when not to and to allow the jbig decoder and bit reverser - * to write to memory when necessary. - */ - tif->tif_flags |= TIFF_NOBITREV; - tif->tif_flags &= ~TIFF_MAPPED; + /* + * These flags are set so the JBIG Codec can control when to reverse + * bits and when not to and to allow the jbig decoder and bit reverser + * to write to memory when necessary. + */ + tif->tif_flags |= TIFF_NOBITREV; + tif->tif_flags &= ~TIFF_MAPPED; - /* Setup the function pointers for encode, decode, and cleanup. */ - tif->tif_setupdecode = JBIGSetupDecode; - tif->tif_decodestrip = JBIGDecode; + /* Setup the function pointers for encode, decode, and cleanup. */ + tif->tif_setupdecode = JBIGSetupDecode; + tif->tif_decodestrip = JBIGDecode; - tif->tif_setupencode = JBIGSetupEncode; - tif->tif_encodestrip = JBIGEncode; + tif->tif_setupencode = JBIGSetupEncode; + tif->tif_encodestrip = JBIGEncode; - return 1; + return 1; } #endif /* JBIG_SUPPORT */ diff --git a/3rdparty/libtiff/tif_jpeg.c b/3rdparty/libtiff/tif_jpeg.c index 385dec5d10..0fbdb3548a 100644 --- a/3rdparty/libtiff/tif_jpeg.c +++ b/3rdparty/libtiff/tif_jpeg.c @@ -1,32 +1,34 @@ -/* $Id: tif_jpeg.c,v 1.108 2012-06-05 03:24:30 fwarmerdam Exp $ */ +/* $Id: tif_jpeg.c,v 1.134 2017-10-17 19:04:47 erouault Exp $ */ /* * Copyright (c) 1994-1997 Sam Leffler * Copyright (c) 1994-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN +#include + #include "tiffiop.h" #ifdef JPEG_SUPPORT @@ -47,6 +49,7 @@ int TIFFFillStrip(TIFF* tif, uint32 strip); int TIFFFillTile(TIFF* tif, uint32 tile); int TIFFReInitJPEG_12( TIFF *tif, int scheme, int is_encode ); +int TIFFJPEGIsFullStripRequired_12(TIFF* tif); /* We undefine FAR to avoid conflict with JPEG definition */ @@ -58,7 +61,7 @@ int TIFFReInitJPEG_12( TIFF *tif, int scheme, int is_encode ); Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is not defined. Unfortunately, the MinGW and Borland compilers include a typedef for INT32, which causes a conflict. MSVC does not include - a conficting typedef given the headers which are included. + a conflicting typedef given the headers which are included. */ #if defined(__BORLANDC__) || defined(__MINGW32__) # define XMD_H 1 @@ -88,9 +91,9 @@ int TIFFReInitJPEG_12( TIFF *tif, int scheme, int is_encode ); #include "jpeglib.h" #include "jerror.h" -/* +/* * Do we want to do special processing suitable for when JSAMPLE is a - * 16bit value? + * 16bit value? */ #if defined(JPEG_LIB_MK1) @@ -136,45 +139,48 @@ typedef struct jpeg_error_mgr jpeg_error_mgr; * and vice versa! */ typedef struct { - union { - struct jpeg_compress_struct c; - struct jpeg_decompress_struct d; - struct jpeg_common_struct comm; - } cinfo; /* NB: must be first */ - int cinfo_initialized; + union { + struct jpeg_compress_struct c; + struct jpeg_decompress_struct d; + struct jpeg_common_struct comm; + } cinfo; /* NB: must be first */ + int cinfo_initialized; - jpeg_error_mgr err; /* libjpeg error manager */ - JMP_BUF exit_jmpbuf; /* for catching libjpeg failures */ - /* - * The following two members could be a union, but - * they're small enough that it's not worth the effort. - */ - jpeg_destination_mgr dest; /* data dest for compression */ - jpeg_source_mgr src; /* data source for decompression */ - /* private state */ - TIFF* tif; /* back link needed by some code */ - uint16 photometric; /* copy of PhotometricInterpretation */ - uint16 h_sampling; /* luminance sampling factors */ - uint16 v_sampling; - tmsize_t bytesperline; /* decompressed bytes per scanline */ - /* pointers to intermediate buffers when processing downsampled data */ - JSAMPARRAY ds_buffer[MAX_COMPONENTS]; - int scancount; /* number of "scanlines" accumulated */ - int samplesperclump; + jpeg_error_mgr err; /* libjpeg error manager */ + JMP_BUF exit_jmpbuf; /* for catching libjpeg failures */ + + struct jpeg_progress_mgr progress; + /* + * The following two members could be a union, but + * they're small enough that it's not worth the effort. + */ + jpeg_destination_mgr dest; /* data dest for compression */ + jpeg_source_mgr src; /* data source for decompression */ + /* private state */ + TIFF* tif; /* back link needed by some code */ + uint16 photometric; /* copy of PhotometricInterpretation */ + uint16 h_sampling; /* luminance sampling factors */ + uint16 v_sampling; + tmsize_t bytesperline; /* decompressed bytes per scanline */ + /* pointers to intermediate buffers when processing downsampled data */ + JSAMPARRAY ds_buffer[MAX_COMPONENTS]; + int scancount; /* number of "scanlines" accumulated */ + int samplesperclump; - TIFFVGetMethod vgetparent; /* super-class method */ - TIFFVSetMethod vsetparent; /* super-class method */ - TIFFPrintMethod printdir; /* super-class method */ - TIFFStripMethod defsparent; /* super-class method */ - TIFFTileMethod deftparent; /* super-class method */ - /* pseudo-tag fields */ - void* jpegtables; /* JPEGTables tag value, or NULL */ - uint32 jpegtables_length; /* number of bytes in same */ - int jpegquality; /* Compression quality level */ - int jpegcolormode; /* Auto RGB<=>YCbCr convert? */ - int jpegtablesmode; /* What to put in JPEGTables */ + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + TIFFPrintMethod printdir; /* super-class method */ + TIFFStripMethod defsparent; /* super-class method */ + TIFFTileMethod deftparent; /* super-class method */ + /* pseudo-tag fields */ + void* jpegtables; /* JPEGTables tag value, or NULL */ + uint32 jpegtables_length; /* number of bytes in same */ + int jpegquality; /* Compression quality level */ + int jpegcolormode; /* Auto RGB<=>YCbCr convert? */ + int jpegtablesmode; /* What to put in JPEGTables */ int ycbcrsampling_fetched; + int max_allowed_scan_number; } JPEGState; #define JState(tif) ((JPEGState*)(tif)->tif_data) @@ -212,13 +218,13 @@ static const TIFFField jpegFields[] = { static void TIFFjpeg_error_exit(j_common_ptr cinfo) { - JPEGState *sp = (JPEGState *) cinfo; /* NB: cinfo assumed first */ - char buffer[JMSG_LENGTH_MAX]; + JPEGState *sp = (JPEGState *) cinfo; /* NB: cinfo assumed first */ + char buffer[JMSG_LENGTH_MAX]; - (*cinfo->err->format_message) (cinfo, buffer); - TIFFErrorExt(sp->tif->tif_clientdata, "JPEGLib", "%s", buffer); /* display the error message */ - jpeg_abort(cinfo); /* clean up libjpeg state */ - LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */ + (*cinfo->err->format_message) (cinfo, buffer); + TIFFErrorExt(sp->tif->tif_clientdata, "JPEGLib", "%s", buffer); /* display the error message */ + jpeg_abort(cinfo); /* clean up libjpeg state */ + LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */ } /* @@ -229,12 +235,39 @@ TIFFjpeg_error_exit(j_common_ptr cinfo) static void TIFFjpeg_output_message(j_common_ptr cinfo) { - char buffer[JMSG_LENGTH_MAX]; + char buffer[JMSG_LENGTH_MAX]; - (*cinfo->err->format_message) (cinfo, buffer); - TIFFWarningExt(((JPEGState *) cinfo)->tif->tif_clientdata, "JPEGLib", "%s", buffer); + (*cinfo->err->format_message) (cinfo, buffer); + TIFFWarningExt(((JPEGState *) cinfo)->tif->tif_clientdata, "JPEGLib", "%s", buffer); } +/* Avoid the risk of denial-of-service on crafted JPEGs with an insane */ +/* number of scans. */ +/* See http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf */ +static void +TIFFjpeg_progress_monitor(j_common_ptr cinfo) +{ + JPEGState *sp = (JPEGState *) cinfo; /* NB: cinfo assumed first */ + if (cinfo->is_decompressor) + { + const int scan_no = + ((j_decompress_ptr)cinfo)->input_scan_number; + if (scan_no >= sp->max_allowed_scan_number) + { + TIFFErrorExt(((JPEGState *) cinfo)->tif->tif_clientdata, + "TIFFjpeg_progress_monitor", + "Scan number %d exceeds maximum scans (%d). This limit " + "can be raised through the LIBTIFF_JPEG_MAX_ALLOWED_SCAN_NUMBER " + "environment variable.", + scan_no, sp->max_allowed_scan_number); + + jpeg_abort(cinfo); /* clean up libjpeg state */ + LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */ + } + } +} + + /* * Interface routines. This layer of routines exists * primarily to limit side-effects from using setjmp. @@ -247,134 +280,155 @@ TIFFjpeg_output_message(j_common_ptr cinfo) static int TIFFjpeg_create_compress(JPEGState* sp) { - /* initialize JPEG error handling */ - sp->cinfo.c.err = jpeg_std_error(&sp->err); - sp->err.error_exit = TIFFjpeg_error_exit; - sp->err.output_message = TIFFjpeg_output_message; + /* initialize JPEG error handling */ + sp->cinfo.c.err = jpeg_std_error(&sp->err); + sp->err.error_exit = TIFFjpeg_error_exit; + sp->err.output_message = TIFFjpeg_output_message; - return CALLVJPEG(sp, jpeg_create_compress(&sp->cinfo.c)); + /* set client_data to avoid UMR warning from tools like Purify */ + sp->cinfo.c.client_data = NULL; + + return CALLVJPEG(sp, jpeg_create_compress(&sp->cinfo.c)); } static int TIFFjpeg_create_decompress(JPEGState* sp) { - /* initialize JPEG error handling */ - sp->cinfo.d.err = jpeg_std_error(&sp->err); - sp->err.error_exit = TIFFjpeg_error_exit; - sp->err.output_message = TIFFjpeg_output_message; + /* initialize JPEG error handling */ + sp->cinfo.d.err = jpeg_std_error(&sp->err); + sp->err.error_exit = TIFFjpeg_error_exit; + sp->err.output_message = TIFFjpeg_output_message; - return CALLVJPEG(sp, jpeg_create_decompress(&sp->cinfo.d)); + /* set client_data to avoid UMR warning from tools like Purify */ + sp->cinfo.d.client_data = NULL; + + return CALLVJPEG(sp, jpeg_create_decompress(&sp->cinfo.d)); } static int TIFFjpeg_set_defaults(JPEGState* sp) { - return CALLVJPEG(sp, jpeg_set_defaults(&sp->cinfo.c)); + return CALLVJPEG(sp, jpeg_set_defaults(&sp->cinfo.c)); } static int TIFFjpeg_set_colorspace(JPEGState* sp, J_COLOR_SPACE colorspace) { - return CALLVJPEG(sp, jpeg_set_colorspace(&sp->cinfo.c, colorspace)); + return CALLVJPEG(sp, jpeg_set_colorspace(&sp->cinfo.c, colorspace)); } static int TIFFjpeg_set_quality(JPEGState* sp, int quality, boolean force_baseline) { - return CALLVJPEG(sp, - jpeg_set_quality(&sp->cinfo.c, quality, force_baseline)); + return CALLVJPEG(sp, + jpeg_set_quality(&sp->cinfo.c, quality, force_baseline)); } static int TIFFjpeg_suppress_tables(JPEGState* sp, boolean suppress) { - return CALLVJPEG(sp, jpeg_suppress_tables(&sp->cinfo.c, suppress)); + return CALLVJPEG(sp, jpeg_suppress_tables(&sp->cinfo.c, suppress)); } static int TIFFjpeg_start_compress(JPEGState* sp, boolean write_all_tables) { - return CALLVJPEG(sp, - jpeg_start_compress(&sp->cinfo.c, write_all_tables)); + return CALLVJPEG(sp, + jpeg_start_compress(&sp->cinfo.c, write_all_tables)); } static int TIFFjpeg_write_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int num_lines) { - return CALLJPEG(sp, -1, (int) jpeg_write_scanlines(&sp->cinfo.c, - scanlines, (JDIMENSION) num_lines)); + return CALLJPEG(sp, -1, (int) jpeg_write_scanlines(&sp->cinfo.c, + scanlines, (JDIMENSION) num_lines)); } static int TIFFjpeg_write_raw_data(JPEGState* sp, JSAMPIMAGE data, int num_lines) { - return CALLJPEG(sp, -1, (int) jpeg_write_raw_data(&sp->cinfo.c, - data, (JDIMENSION) num_lines)); + return CALLJPEG(sp, -1, (int) jpeg_write_raw_data(&sp->cinfo.c, + data, (JDIMENSION) num_lines)); } static int TIFFjpeg_finish_compress(JPEGState* sp) { - return CALLVJPEG(sp, jpeg_finish_compress(&sp->cinfo.c)); + return CALLVJPEG(sp, jpeg_finish_compress(&sp->cinfo.c)); } static int TIFFjpeg_write_tables(JPEGState* sp) { - return CALLVJPEG(sp, jpeg_write_tables(&sp->cinfo.c)); + return CALLVJPEG(sp, jpeg_write_tables(&sp->cinfo.c)); } static int TIFFjpeg_read_header(JPEGState* sp, boolean require_image) { - return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image)); + return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image)); +} + +static int +TIFFjpeg_has_multiple_scans(JPEGState* sp) +{ + return CALLJPEG(sp, 0, jpeg_has_multiple_scans(&sp->cinfo.d)); } static int TIFFjpeg_start_decompress(JPEGState* sp) { - return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d)); + const char* sz_max_allowed_scan_number; + /* progress monitor */ + sp->cinfo.d.progress = &sp->progress; + sp->progress.progress_monitor = TIFFjpeg_progress_monitor; + sp->max_allowed_scan_number = 100; + sz_max_allowed_scan_number = getenv("LIBTIFF_JPEG_MAX_ALLOWED_SCAN_NUMBER"); + if( sz_max_allowed_scan_number ) + sp->max_allowed_scan_number = atoi(sz_max_allowed_scan_number); + + return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d)); } static int TIFFjpeg_read_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int max_lines) { - return CALLJPEG(sp, -1, (int) jpeg_read_scanlines(&sp->cinfo.d, - scanlines, (JDIMENSION) max_lines)); + return CALLJPEG(sp, -1, (int) jpeg_read_scanlines(&sp->cinfo.d, + scanlines, (JDIMENSION) max_lines)); } static int TIFFjpeg_read_raw_data(JPEGState* sp, JSAMPIMAGE data, int max_lines) { - return CALLJPEG(sp, -1, (int) jpeg_read_raw_data(&sp->cinfo.d, - data, (JDIMENSION) max_lines)); + return CALLJPEG(sp, -1, (int) jpeg_read_raw_data(&sp->cinfo.d, + data, (JDIMENSION) max_lines)); } static int TIFFjpeg_finish_decompress(JPEGState* sp) { - return CALLJPEG(sp, -1, (int) jpeg_finish_decompress(&sp->cinfo.d)); + return CALLJPEG(sp, -1, (int) jpeg_finish_decompress(&sp->cinfo.d)); } static int TIFFjpeg_abort(JPEGState* sp) { - return CALLVJPEG(sp, jpeg_abort(&sp->cinfo.comm)); + return CALLVJPEG(sp, jpeg_abort(&sp->cinfo.comm)); } static int TIFFjpeg_destroy(JPEGState* sp) { - return CALLVJPEG(sp, jpeg_destroy(&sp->cinfo.comm)); + return CALLVJPEG(sp, jpeg_destroy(&sp->cinfo.comm)); } static JSAMPARRAY TIFFjpeg_alloc_sarray(JPEGState* sp, int pool_id, - JDIMENSION samplesperrow, JDIMENSION numrows) + JDIMENSION samplesperrow, JDIMENSION numrows) { - return CALLJPEG(sp, (JSAMPARRAY) NULL, - (*sp->cinfo.comm.mem->alloc_sarray) - (&sp->cinfo.comm, pool_id, samplesperrow, numrows)); + return CALLJPEG(sp, (JSAMPARRAY) NULL, + (*sp->cinfo.comm.mem->alloc_sarray) + (&sp->cinfo.comm, pool_id, samplesperrow, numrows)); } /* @@ -386,21 +440,21 @@ TIFFjpeg_alloc_sarray(JPEGState* sp, int pool_id, static void std_init_destination(j_compress_ptr cinfo) { - JPEGState* sp = (JPEGState*) cinfo; - TIFF* tif = sp->tif; + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; - sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata; - sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize; + sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata; + sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize; } static boolean std_empty_output_buffer(j_compress_ptr cinfo) { - JPEGState* sp = (JPEGState*) cinfo; - TIFF* tif = sp->tif; + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; - /* the entire buffer has been filled */ - tif->tif_rawcc = tif->tif_rawdatasize; + /* the entire buffer has been filled */ + tif->tif_rawcc = tif->tif_rawdatasize; #ifdef IPPJ_HUFF /* @@ -414,33 +468,33 @@ std_empty_output_buffer(j_compress_ptr cinfo) } #endif - TIFFFlushData1(tif); - sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata; - sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize; + TIFFFlushData1(tif); + sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata; + sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize; - return (TRUE); + return (TRUE); } static void std_term_destination(j_compress_ptr cinfo) { - JPEGState* sp = (JPEGState*) cinfo; - TIFF* tif = sp->tif; + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; - tif->tif_rawcp = (uint8*) sp->dest.next_output_byte; - tif->tif_rawcc = - tif->tif_rawdatasize - (tmsize_t) sp->dest.free_in_buffer; - /* NB: libtiff does the final buffer flush */ + tif->tif_rawcp = (uint8*) sp->dest.next_output_byte; + tif->tif_rawcc = + tif->tif_rawdatasize - (tmsize_t) sp->dest.free_in_buffer; + /* NB: libtiff does the final buffer flush */ } static void TIFFjpeg_data_dest(JPEGState* sp, TIFF* tif) { - (void) tif; - sp->cinfo.c.dest = &sp->dest; - sp->dest.init_destination = std_init_destination; - sp->dest.empty_output_buffer = std_empty_output_buffer; - sp->dest.term_destination = std_term_destination; + (void) tif; + sp->cinfo.c.dest = &sp->dest; + sp->dest.init_destination = std_init_destination; + sp->dest.empty_output_buffer = std_empty_output_buffer; + sp->dest.term_destination = std_term_destination; } /* @@ -450,62 +504,62 @@ TIFFjpeg_data_dest(JPEGState* sp, TIFF* tif) static void tables_init_destination(j_compress_ptr cinfo) { - JPEGState* sp = (JPEGState*) cinfo; + JPEGState* sp = (JPEGState*) cinfo; - /* while building, jpegtables_length is allocated buffer size */ - sp->dest.next_output_byte = (JOCTET*) sp->jpegtables; - sp->dest.free_in_buffer = (size_t) sp->jpegtables_length; + /* while building, jpegtables_length is allocated buffer size */ + sp->dest.next_output_byte = (JOCTET*) sp->jpegtables; + sp->dest.free_in_buffer = (size_t) sp->jpegtables_length; } static boolean tables_empty_output_buffer(j_compress_ptr cinfo) { - JPEGState* sp = (JPEGState*) cinfo; - void* newbuf; + JPEGState* sp = (JPEGState*) cinfo; + void* newbuf; - /* the entire buffer has been filled; enlarge it by 1000 bytes */ - newbuf = _TIFFrealloc((void*) sp->jpegtables, - (tmsize_t) (sp->jpegtables_length + 1000)); - if (newbuf == NULL) - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100); - sp->dest.next_output_byte = (JOCTET*) newbuf + sp->jpegtables_length; - sp->dest.free_in_buffer = (size_t) 1000; - sp->jpegtables = newbuf; - sp->jpegtables_length += 1000; - return (TRUE); + /* the entire buffer has been filled; enlarge it by 1000 bytes */ + newbuf = _TIFFrealloc((void*) sp->jpegtables, + (tmsize_t) (sp->jpegtables_length + 1000)); + if (newbuf == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100); + sp->dest.next_output_byte = (JOCTET*) newbuf + sp->jpegtables_length; + sp->dest.free_in_buffer = (size_t) 1000; + sp->jpegtables = newbuf; + sp->jpegtables_length += 1000; + return (TRUE); } static void tables_term_destination(j_compress_ptr cinfo) { - JPEGState* sp = (JPEGState*) cinfo; + JPEGState* sp = (JPEGState*) cinfo; - /* set tables length to number of bytes actually emitted */ - sp->jpegtables_length -= (uint32) sp->dest.free_in_buffer; + /* set tables length to number of bytes actually emitted */ + sp->jpegtables_length -= (uint32) sp->dest.free_in_buffer; } static int TIFFjpeg_tables_dest(JPEGState* sp, TIFF* tif) { - (void) tif; - /* - * Allocate a working buffer for building tables. - * Initial size is 1000 bytes, which is usually adequate. - */ - if (sp->jpegtables) - _TIFFfree(sp->jpegtables); - sp->jpegtables_length = 1000; - sp->jpegtables = (void*) _TIFFmalloc((tmsize_t) sp->jpegtables_length); - if (sp->jpegtables == NULL) { - sp->jpegtables_length = 0; - TIFFErrorExt(sp->tif->tif_clientdata, "TIFFjpeg_tables_dest", "No space for JPEGTables"); - return (0); - } - sp->cinfo.c.dest = &sp->dest; - sp->dest.init_destination = tables_init_destination; - sp->dest.empty_output_buffer = tables_empty_output_buffer; - sp->dest.term_destination = tables_term_destination; - return (1); + (void) tif; + /* + * Allocate a working buffer for building tables. + * Initial size is 1000 bytes, which is usually adequate. + */ + if (sp->jpegtables) + _TIFFfree(sp->jpegtables); + sp->jpegtables_length = 1000; + sp->jpegtables = (void*) _TIFFmalloc((tmsize_t) sp->jpegtables_length); + if (sp->jpegtables == NULL) { + sp->jpegtables_length = 0; + TIFFErrorExt(sp->tif->tif_clientdata, "TIFFjpeg_tables_dest", "No space for JPEGTables"); + return (0); + } + sp->cinfo.c.dest = &sp->dest; + sp->dest.init_destination = tables_init_destination; + sp->dest.empty_output_buffer = tables_empty_output_buffer; + sp->dest.term_destination = tables_term_destination; + return (1); } /* @@ -516,27 +570,27 @@ TIFFjpeg_tables_dest(JPEGState* sp, TIFF* tif) static void std_init_source(j_decompress_ptr cinfo) { - JPEGState* sp = (JPEGState*) cinfo; - TIFF* tif = sp->tif; + JPEGState* sp = (JPEGState*) cinfo; + TIFF* tif = sp->tif; - sp->src.next_input_byte = (const JOCTET*) tif->tif_rawdata; - sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc; + sp->src.next_input_byte = (const JOCTET*) tif->tif_rawdata; + sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc; } static boolean std_fill_input_buffer(j_decompress_ptr cinfo) { - JPEGState* sp = (JPEGState* ) cinfo; - static const JOCTET dummy_EOI[2] = { 0xFF, JPEG_EOI }; + JPEGState* sp = (JPEGState* ) cinfo; + static const JOCTET dummy_EOI[2] = { 0xFF, JPEG_EOI }; #ifdef IPPJ_HUFF /* * The Intel IPP performance library does not necessarily read the whole * input buffer in one pass, so it is possible to get here with data - * yet to read. - * + * yet to read. + * * We just return without doing anything, until the entire buffer has - * been read. + * been read. * http://trac.osgeo.org/gdal/wiki/JpegIPP */ if( sp->src.bytes_in_buffer > 0 ) { @@ -544,56 +598,55 @@ std_fill_input_buffer(j_decompress_ptr cinfo) } #endif - /* + /* * Normally the whole strip/tile is read and so we don't need to do * a fill. In the case of CHUNKY_STRIP_READ_SUPPORT we might not have * all the data, but the rawdata is refreshed between scanlines and - * we push this into the io machinery in JPEGDecode(). + * we push this into the io machinery in JPEGDecode(). * http://trac.osgeo.org/gdal/ticket/3894 - */ - - WARNMS(cinfo, JWRN_JPEG_EOF); - /* insert a fake EOI marker */ - sp->src.next_input_byte = dummy_EOI; - sp->src.bytes_in_buffer = 2; - return (TRUE); + */ + + WARNMS(cinfo, JWRN_JPEG_EOF); + /* insert a fake EOI marker */ + sp->src.next_input_byte = dummy_EOI; + sp->src.bytes_in_buffer = 2; + return (TRUE); } static void std_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { - JPEGState* sp = (JPEGState*) cinfo; + JPEGState* sp = (JPEGState*) cinfo; - if (num_bytes > 0) { - if ((size_t)num_bytes > sp->src.bytes_in_buffer) { - /* oops, buffer overrun */ - (void) std_fill_input_buffer(cinfo); - } else { - sp->src.next_input_byte += (size_t) num_bytes; - sp->src.bytes_in_buffer -= (size_t) num_bytes; - } - } + if (num_bytes > 0) { + if ((size_t)num_bytes > sp->src.bytes_in_buffer) { + /* oops, buffer overrun */ + (void) std_fill_input_buffer(cinfo); + } else { + sp->src.next_input_byte += (size_t) num_bytes; + sp->src.bytes_in_buffer -= (size_t) num_bytes; + } + } } static void std_term_source(j_decompress_ptr cinfo) { - /* No work necessary here */ - (void) cinfo; + /* No work necessary here */ + (void) cinfo; } static void -TIFFjpeg_data_src(JPEGState* sp, TIFF* tif) +TIFFjpeg_data_src(JPEGState* sp) { - (void) tif; - sp->cinfo.d.src = &sp->src; - sp->src.init_source = std_init_source; - sp->src.fill_input_buffer = std_fill_input_buffer; - sp->src.skip_input_data = std_skip_input_data; - sp->src.resync_to_restart = jpeg_resync_to_restart; - sp->src.term_source = std_term_source; - sp->src.bytes_in_buffer = 0; /* for safety */ - sp->src.next_input_byte = NULL; + sp->cinfo.d.src = &sp->src; + sp->src.init_source = std_init_source; + sp->src.fill_input_buffer = std_fill_input_buffer; + sp->src.skip_input_data = std_skip_input_data; + sp->src.resync_to_restart = jpeg_resync_to_restart; + sp->src.term_source = std_term_source; + sp->src.bytes_in_buffer = 0; /* for safety */ + sp->src.next_input_byte = NULL; } /* @@ -604,17 +657,17 @@ TIFFjpeg_data_src(JPEGState* sp, TIFF* tif) static void tables_init_source(j_decompress_ptr cinfo) { - JPEGState* sp = (JPEGState*) cinfo; + JPEGState* sp = (JPEGState*) cinfo; - sp->src.next_input_byte = (const JOCTET*) sp->jpegtables; - sp->src.bytes_in_buffer = (size_t) sp->jpegtables_length; + sp->src.next_input_byte = (const JOCTET*) sp->jpegtables; + sp->src.bytes_in_buffer = (size_t) sp->jpegtables_length; } static void -TIFFjpeg_tables_src(JPEGState* sp, TIFF* tif) +TIFFjpeg_tables_src(JPEGState* sp) { - TIFFjpeg_data_src(sp, tif); - sp->src.init_source = tables_init_source; + TIFFjpeg_data_src(sp); + sp->src.init_source = tables_init_source; } /* @@ -626,27 +679,27 @@ TIFFjpeg_tables_src(JPEGState* sp, TIFF* tif) */ static int alloc_downsampled_buffers(TIFF* tif, jpeg_component_info* comp_info, - int num_components) + int num_components) { - JPEGState* sp = JState(tif); - int ci; - jpeg_component_info* compptr; - JSAMPARRAY buf; - int samples_per_clump = 0; + JPEGState* sp = JState(tif); + int ci; + jpeg_component_info* compptr; + JSAMPARRAY buf; + int samples_per_clump = 0; - for (ci = 0, compptr = comp_info; ci < num_components; - ci++, compptr++) { - samples_per_clump += compptr->h_samp_factor * - compptr->v_samp_factor; - buf = TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE, - compptr->width_in_blocks * DCTSIZE, - (JDIMENSION) (compptr->v_samp_factor*DCTSIZE)); - if (buf == NULL) - return (0); - sp->ds_buffer[ci] = buf; - } - sp->samplesperclump = samples_per_clump; - return (1); + for (ci = 0, compptr = comp_info; ci < num_components; + ci++, compptr++) { + samples_per_clump += compptr->h_samp_factor * + compptr->v_samp_factor; + buf = TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE, + compptr->width_in_blocks * DCTSIZE, + (JDIMENSION) (compptr->v_samp_factor*DCTSIZE)); + if (buf == NULL) + return (0); + sp->ds_buffer[ci] = buf; + } + sp->samplesperclump = samples_per_clump; + return (1); } @@ -658,7 +711,9 @@ alloc_downsampled_buffers(TIFF* tif, jpeg_component_info* comp_info, #define JPEG_MARKER_SOF0 0xC0 #define JPEG_MARKER_SOF1 0xC1 -#define JPEG_MARKER_SOF3 0xC3 +#define JPEG_MARKER_SOF2 0xC2 +#define JPEG_MARKER_SOF9 0xC9 +#define JPEG_MARKER_SOF10 0xCA #define JPEG_MARKER_DHT 0xC4 #define JPEG_MARKER_SOI 0xD8 #define JPEG_MARKER_SOS 0xDA @@ -668,14 +723,14 @@ alloc_downsampled_buffers(TIFF* tif, jpeg_component_info* comp_info, #define JPEG_MARKER_COM 0xFE struct JPEGFixupTagsSubsamplingData { - TIFF* tif; - void* buffer; - uint32 buffersize; - uint8* buffercurrentbyte; - uint32 bufferbytesleft; - uint64 fileoffset; - uint64 filebytesleft; - uint8 filepositioned; + TIFF* tif; + void* buffer; + uint32 buffersize; + uint8* buffercurrentbyte; + uint32 bufferbytesleft; + uint64 fileoffset; + uint64 filebytesleft; + uint8 filepositioned; }; static void JPEGFixupTagsSubsampling(TIFF* tif); static int JPEGFixupTagsSubsamplingSec(struct JPEGFixupTagsSubsamplingData* data); @@ -689,13 +744,15 @@ static int JPEGFixupTags(TIFF* tif) { #ifdef CHECK_JPEG_YCBCR_SUBSAMPLING - if ((tif->tif_dir.td_photometric==PHOTOMETRIC_YCBCR)&& - (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG)&& - (tif->tif_dir.td_samplesperpixel==3)) - JPEGFixupTagsSubsampling(tif); + JPEGState* sp = JState(tif); + if ((tif->tif_dir.td_photometric==PHOTOMETRIC_YCBCR)&& + (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG)&& + (tif->tif_dir.td_samplesperpixel==3) && + !sp->ycbcrsampling_fetched) + JPEGFixupTagsSubsampling(tif); #endif - - return(1); + + return(1); } #ifdef CHECK_JPEG_YCBCR_SUBSAMPLING @@ -703,32 +760,33 @@ JPEGFixupTags(TIFF* tif) static void JPEGFixupTagsSubsampling(TIFF* tif) { - /* - * Some JPEG-in-TIFF produces do not emit the YCBCRSUBSAMPLING values in - * the TIFF tags, but still use non-default (2,2) values within the jpeg - * data stream itself. In order for TIFF applications to work properly - * - for instance to get the strip buffer size right - it is imperative - * that the subsampling be available before we start reading the image - * data normally. This function will attempt to analyze the first strip in - * order to get the sampling values from the jpeg data stream. - * - * Note that JPEGPreDeocode() will produce a fairly loud warning when the - * discovered sampling does not match the default sampling (2,2) or whatever - * was actually in the tiff tags. - * - * See the bug in bugzilla for details: - * - * http://bugzilla.remotesensing.org/show_bug.cgi?id=168 - * - * Frank Warmerdam, July 2002 - * Joris Van Damme, May 2007 - */ - static const char module[] = "JPEGFixupTagsSubsampling"; - struct JPEGFixupTagsSubsamplingData m; + /* + * Some JPEG-in-TIFF produces do not emit the YCBCRSUBSAMPLING values in + * the TIFF tags, but still use non-default (2,2) values within the jpeg + * data stream itself. In order for TIFF applications to work properly + * - for instance to get the strip buffer size right - it is imperative + * that the subsampling be available before we start reading the image + * data normally. This function will attempt to analyze the first strip in + * order to get the sampling values from the jpeg data stream. + * + * Note that JPEGPreDeocode() will produce a fairly loud warning when the + * discovered sampling does not match the default sampling (2,2) or whatever + * was actually in the tiff tags. + * + * See the bug in bugzilla for details: + * + * http://bugzilla.remotesensing.org/show_bug.cgi?id=168 + * + * Frank Warmerdam, July 2002 + * Joris Van Damme, May 2007 + */ + static const char module[] = "JPEGFixupTagsSubsampling"; + struct JPEGFixupTagsSubsamplingData m; _TIFFFillStriles( tif ); - + if( tif->tif_dir.td_stripbytecount == NULL + || tif->tif_dir.td_stripoffset == NULL || tif->tif_dir.td_stripbytecount[0] == 0 ) { /* Do not even try to check if the first strip/tile does not @@ -737,208 +795,211 @@ JPEGFixupTagsSubsampling(TIFF* tif) return; } - m.tif=tif; - m.buffersize=2048; - m.buffer=_TIFFmalloc(m.buffersize); - if (m.buffer==NULL) - { - TIFFWarningExt(tif->tif_clientdata,module, - "Unable to allocate memory for auto-correcting of subsampling values; auto-correcting skipped"); - return; - } - m.buffercurrentbyte=NULL; - m.bufferbytesleft=0; - m.fileoffset=tif->tif_dir.td_stripoffset[0]; - m.filepositioned=0; - m.filebytesleft=tif->tif_dir.td_stripbytecount[0]; - if (!JPEGFixupTagsSubsamplingSec(&m)) - TIFFWarningExt(tif->tif_clientdata,module, - "Unable to auto-correct subsampling values, likely corrupt JPEG compressed data in first strip/tile; auto-correcting skipped"); - _TIFFfree(m.buffer); + m.tif=tif; + m.buffersize=2048; + m.buffer=_TIFFmalloc(m.buffersize); + if (m.buffer==NULL) + { + TIFFWarningExt(tif->tif_clientdata,module, + "Unable to allocate memory for auto-correcting of subsampling values; auto-correcting skipped"); + return; + } + m.buffercurrentbyte=NULL; + m.bufferbytesleft=0; + m.fileoffset=tif->tif_dir.td_stripoffset[0]; + m.filepositioned=0; + m.filebytesleft=tif->tif_dir.td_stripbytecount[0]; + if (!JPEGFixupTagsSubsamplingSec(&m)) + TIFFWarningExt(tif->tif_clientdata,module, + "Unable to auto-correct subsampling values, likely corrupt JPEG compressed data in first strip/tile; auto-correcting skipped"); + _TIFFfree(m.buffer); } static int JPEGFixupTagsSubsamplingSec(struct JPEGFixupTagsSubsamplingData* data) { - static const char module[] = "JPEGFixupTagsSubsamplingSec"; - uint8 m; - while (1) - { - while (1) - { - if (!JPEGFixupTagsSubsamplingReadByte(data,&m)) - return(0); - if (m==255) - break; - } - while (1) - { - if (!JPEGFixupTagsSubsamplingReadByte(data,&m)) - return(0); - if (m!=255) - break; - } - switch (m) - { - case JPEG_MARKER_SOI: - /* this type of marker has no data and should be skipped */ - break; - case JPEG_MARKER_COM: - case JPEG_MARKER_APP0: - case JPEG_MARKER_APP0+1: - case JPEG_MARKER_APP0+2: - case JPEG_MARKER_APP0+3: - case JPEG_MARKER_APP0+4: - case JPEG_MARKER_APP0+5: - case JPEG_MARKER_APP0+6: - case JPEG_MARKER_APP0+7: - case JPEG_MARKER_APP0+8: - case JPEG_MARKER_APP0+9: - case JPEG_MARKER_APP0+10: - case JPEG_MARKER_APP0+11: - case JPEG_MARKER_APP0+12: - case JPEG_MARKER_APP0+13: - case JPEG_MARKER_APP0+14: - case JPEG_MARKER_APP0+15: - case JPEG_MARKER_DQT: - case JPEG_MARKER_SOS: - case JPEG_MARKER_DHT: - case JPEG_MARKER_DRI: - /* this type of marker has data, but it has no use to us and should be skipped */ - { - uint16 n; - if (!JPEGFixupTagsSubsamplingReadWord(data,&n)) - return(0); - if (n<2) - return(0); - n-=2; - if (n>0) - JPEGFixupTagsSubsamplingSkip(data,n); - } - break; - case JPEG_MARKER_SOF0: - case JPEG_MARKER_SOF1: - /* this marker contains the subsampling factors we're scanning for */ - { - uint16 n; - uint16 o; - uint8 p; - uint8 ph,pv; - if (!JPEGFixupTagsSubsamplingReadWord(data,&n)) - return(0); - if (n!=8+data->tif->tif_dir.td_samplesperpixel*3) - return(0); - JPEGFixupTagsSubsamplingSkip(data,7); - if (!JPEGFixupTagsSubsamplingReadByte(data,&p)) - return(0); - ph=(p>>4); - pv=(p&15); - JPEGFixupTagsSubsamplingSkip(data,1); - for (o=1; otif->tif_dir.td_samplesperpixel; o++) - { - JPEGFixupTagsSubsamplingSkip(data,1); - if (!JPEGFixupTagsSubsamplingReadByte(data,&p)) - return(0); - if (p!=0x11) - { - TIFFWarningExt(data->tif->tif_clientdata,module, - "Subsampling values inside JPEG compressed data have no TIFF equivalent, auto-correction of TIFF subsampling values failed"); - return(1); - } - JPEGFixupTagsSubsamplingSkip(data,1); - } - if (((ph!=1)&&(ph!=2)&&(ph!=4))||((pv!=1)&&(pv!=2)&&(pv!=4))) - { - TIFFWarningExt(data->tif->tif_clientdata,module, - "Subsampling values inside JPEG compressed data have no TIFF equivalent, auto-correction of TIFF subsampling values failed"); - return(1); - } - if ((ph!=data->tif->tif_dir.td_ycbcrsubsampling[0])||(pv!=data->tif->tif_dir.td_ycbcrsubsampling[1])) - { - TIFFWarningExt(data->tif->tif_clientdata,module, - "Auto-corrected former TIFF subsampling values [%d,%d] to match subsampling values inside JPEG compressed data [%d,%d]", - (int)data->tif->tif_dir.td_ycbcrsubsampling[0], - (int)data->tif->tif_dir.td_ycbcrsubsampling[1], - (int)ph,(int)pv); - data->tif->tif_dir.td_ycbcrsubsampling[0]=ph; - data->tif->tif_dir.td_ycbcrsubsampling[1]=pv; - } - } - return(1); - default: - return(0); - } - } + static const char module[] = "JPEGFixupTagsSubsamplingSec"; + uint8 m; + while (1) + { + while (1) + { + if (!JPEGFixupTagsSubsamplingReadByte(data,&m)) + return(0); + if (m==255) + break; + } + while (1) + { + if (!JPEGFixupTagsSubsamplingReadByte(data,&m)) + return(0); + if (m!=255) + break; + } + switch (m) + { + case JPEG_MARKER_SOI: + /* this type of marker has no data and should be skipped */ + break; + case JPEG_MARKER_COM: + case JPEG_MARKER_APP0: + case JPEG_MARKER_APP0+1: + case JPEG_MARKER_APP0+2: + case JPEG_MARKER_APP0+3: + case JPEG_MARKER_APP0+4: + case JPEG_MARKER_APP0+5: + case JPEG_MARKER_APP0+6: + case JPEG_MARKER_APP0+7: + case JPEG_MARKER_APP0+8: + case JPEG_MARKER_APP0+9: + case JPEG_MARKER_APP0+10: + case JPEG_MARKER_APP0+11: + case JPEG_MARKER_APP0+12: + case JPEG_MARKER_APP0+13: + case JPEG_MARKER_APP0+14: + case JPEG_MARKER_APP0+15: + case JPEG_MARKER_DQT: + case JPEG_MARKER_SOS: + case JPEG_MARKER_DHT: + case JPEG_MARKER_DRI: + /* this type of marker has data, but it has no use to us and should be skipped */ + { + uint16 n; + if (!JPEGFixupTagsSubsamplingReadWord(data,&n)) + return(0); + if (n<2) + return(0); + n-=2; + if (n>0) + JPEGFixupTagsSubsamplingSkip(data,n); + } + break; + case JPEG_MARKER_SOF0: /* Baseline sequential Huffman */ + case JPEG_MARKER_SOF1: /* Extended sequential Huffman */ + case JPEG_MARKER_SOF2: /* Progressive Huffman: normally not allowed by TechNote, but that doesn't hurt supporting it */ + case JPEG_MARKER_SOF9: /* Extended sequential arithmetic */ + case JPEG_MARKER_SOF10: /* Progressive arithmetic: normally not allowed by TechNote, but that doesn't hurt supporting it */ + /* this marker contains the subsampling factors we're scanning for */ + { + uint16 n; + uint16 o; + uint8 p; + uint8 ph,pv; + if (!JPEGFixupTagsSubsamplingReadWord(data,&n)) + return(0); + if (n!=8+data->tif->tif_dir.td_samplesperpixel*3) + return(0); + JPEGFixupTagsSubsamplingSkip(data,7); + if (!JPEGFixupTagsSubsamplingReadByte(data,&p)) + return(0); + ph=(p>>4); + pv=(p&15); + JPEGFixupTagsSubsamplingSkip(data,1); + for (o=1; otif->tif_dir.td_samplesperpixel; o++) + { + JPEGFixupTagsSubsamplingSkip(data,1); + if (!JPEGFixupTagsSubsamplingReadByte(data,&p)) + return(0); + if (p!=0x11) + { + TIFFWarningExt(data->tif->tif_clientdata,module, + "Subsampling values inside JPEG compressed data have no TIFF equivalent, auto-correction of TIFF subsampling values failed"); + return(1); + } + JPEGFixupTagsSubsamplingSkip(data,1); + } + if (((ph!=1)&&(ph!=2)&&(ph!=4))||((pv!=1)&&(pv!=2)&&(pv!=4))) + { + TIFFWarningExt(data->tif->tif_clientdata,module, + "Subsampling values inside JPEG compressed data have no TIFF equivalent, auto-correction of TIFF subsampling values failed"); + return(1); + } + if ((ph!=data->tif->tif_dir.td_ycbcrsubsampling[0])||(pv!=data->tif->tif_dir.td_ycbcrsubsampling[1])) + { + TIFFWarningExt(data->tif->tif_clientdata,module, + "Auto-corrected former TIFF subsampling values [%d,%d] to match subsampling values inside JPEG compressed data [%d,%d]", + (int)data->tif->tif_dir.td_ycbcrsubsampling[0], + (int)data->tif->tif_dir.td_ycbcrsubsampling[1], + (int)ph,(int)pv); + data->tif->tif_dir.td_ycbcrsubsampling[0]=ph; + data->tif->tif_dir.td_ycbcrsubsampling[1]=pv; + } + } + return(1); + default: + return(0); + } + } } static int JPEGFixupTagsSubsamplingReadByte(struct JPEGFixupTagsSubsamplingData* data, uint8* result) { - if (data->bufferbytesleft==0) - { - uint32 m; - if (data->filebytesleft==0) - return(0); - if (!data->filepositioned) - { - TIFFSeekFile(data->tif,data->fileoffset,SEEK_SET); - data->filepositioned=1; - } - m=data->buffersize; - if ((uint64)m>data->filebytesleft) - m=(uint32)data->filebytesleft; - assert(m<0x80000000UL); - if (TIFFReadFile(data->tif,data->buffer,(tmsize_t)m)!=(tmsize_t)m) - return(0); - data->buffercurrentbyte=data->buffer; - data->bufferbytesleft=m; - data->fileoffset+=m; - data->filebytesleft-=m; - } - *result=*data->buffercurrentbyte; - data->buffercurrentbyte++; - data->bufferbytesleft--; - return(1); + if (data->bufferbytesleft==0) + { + uint32 m; + if (data->filebytesleft==0) + return(0); + if (!data->filepositioned) + { + TIFFSeekFile(data->tif,data->fileoffset,SEEK_SET); + data->filepositioned=1; + } + m=data->buffersize; + if ((uint64)m>data->filebytesleft) + m=(uint32)data->filebytesleft; + assert(m<0x80000000UL); + if (TIFFReadFile(data->tif,data->buffer,(tmsize_t)m)!=(tmsize_t)m) + return(0); + data->buffercurrentbyte=data->buffer; + data->bufferbytesleft=m; + data->fileoffset+=m; + data->filebytesleft-=m; + } + *result=*data->buffercurrentbyte; + data->buffercurrentbyte++; + data->bufferbytesleft--; + return(1); } static int JPEGFixupTagsSubsamplingReadWord(struct JPEGFixupTagsSubsamplingData* data, uint16* result) { - uint8 ma; - uint8 mb; - if (!JPEGFixupTagsSubsamplingReadByte(data,&ma)) - return(0); - if (!JPEGFixupTagsSubsamplingReadByte(data,&mb)) - return(0); - *result=(ma<<8)|mb; - return(1); + uint8 ma; + uint8 mb; + if (!JPEGFixupTagsSubsamplingReadByte(data,&ma)) + return(0); + if (!JPEGFixupTagsSubsamplingReadByte(data,&mb)) + return(0); + *result=(ma<<8)|mb; + return(1); } static void JPEGFixupTagsSubsamplingSkip(struct JPEGFixupTagsSubsamplingData* data, uint16 skiplength) { - if ((uint32)skiplength<=data->bufferbytesleft) - { - data->buffercurrentbyte+=skiplength; - data->bufferbytesleft-=skiplength; - } - else - { - uint16 m; - m=skiplength-data->bufferbytesleft; - if (m<=data->filebytesleft) - { - data->bufferbytesleft=0; - data->fileoffset+=m; - data->filebytesleft-=m; - data->filepositioned=0; - } - else - { - data->bufferbytesleft=0; - data->filebytesleft=0; - } - } + if ((uint32)skiplength<=data->bufferbytesleft) + { + data->buffercurrentbyte+=skiplength; + data->bufferbytesleft-=skiplength; + } + else + { + uint16 m; + m=(uint16)(skiplength-data->bufferbytesleft); + if (m<=data->filebytesleft) + { + data->bufferbytesleft=0; + data->fileoffset+=m; + data->filebytesleft-=m; + data->filepositioned=0; + } + else + { + data->bufferbytesleft=0; + data->filebytesleft=0; + } + } } #endif @@ -947,337 +1008,479 @@ JPEGFixupTagsSubsamplingSkip(struct JPEGFixupTagsSubsamplingData* data, uint16 s static int JPEGSetupDecode(TIFF* tif) { - JPEGState* sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; #if defined(JPEG_DUAL_MODE_8_12) && !defined(TIFFInitJPEG) if( tif->tif_dir.td_bitspersample == 12 ) return TIFFReInitJPEG_12( tif, COMPRESSION_JPEG, 0 ); #endif - JPEGInitializeLibJPEG( tif, TRUE ); + JPEGInitializeLibJPEG( tif, TRUE ); - assert(sp != NULL); - assert(sp->cinfo.comm.is_decompressor); + assert(sp != NULL); + assert(sp->cinfo.comm.is_decompressor); - /* Read JPEGTables if it is present */ - if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) { - TIFFjpeg_tables_src(sp, tif); - if(TIFFjpeg_read_header(sp,FALSE) != JPEG_HEADER_TABLES_ONLY) { - TIFFErrorExt(tif->tif_clientdata, "JPEGSetupDecode", "Bogus JPEGTables field"); - return (0); - } + /* Read JPEGTables if it is present */ + if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) { + TIFFjpeg_tables_src(sp); + if(TIFFjpeg_read_header(sp,FALSE) != JPEG_HEADER_TABLES_ONLY) { + TIFFErrorExt(tif->tif_clientdata, "JPEGSetupDecode", "Bogus JPEGTables field"); + return (0); + } + } + + /* Grab parameters that are same for all strips/tiles */ + sp->photometric = td->td_photometric; + switch (sp->photometric) { + case PHOTOMETRIC_YCBCR: + sp->h_sampling = td->td_ycbcrsubsampling[0]; + sp->v_sampling = td->td_ycbcrsubsampling[1]; + break; + default: + /* TIFF 6.0 forbids subsampling of all other color spaces */ + sp->h_sampling = 1; + sp->v_sampling = 1; + break; + } + + /* Set up for reading normal data */ + TIFFjpeg_data_src(sp); + tif->tif_postdecode = _TIFFNoPostDecode; /* override byte swapping */ + return (1); +} + +/* Returns 1 if the full strip should be read, even when doing scanline per */ +/* scanline decoding. This happens when the JPEG stream uses multiple scans. */ +/* Currently only called in CHUNKY_STRIP_READ_SUPPORT mode through */ +/* scanline interface. */ +/* Only reads tif->tif_dir.td_bitspersample, tif->tif_rawdata and */ +/* tif->tif_rawcc members. */ +/* Can be called independently of the usual setup/predecode/decode states */ +int TIFFJPEGIsFullStripRequired(TIFF* tif) +{ + int ret; + JPEGState state; + +#if defined(JPEG_DUAL_MODE_8_12) && !defined(TIFFJPEGIsFullStripRequired) + if( tif->tif_dir.td_bitspersample == 12 ) + return TIFFJPEGIsFullStripRequired_12( tif ); +#endif + + memset(&state, 0, sizeof(JPEGState)); + state.tif = tif; + + TIFFjpeg_create_decompress(&state); + + TIFFjpeg_data_src(&state); + + if (TIFFjpeg_read_header(&state, TRUE) != JPEG_HEADER_OK) + { + TIFFjpeg_destroy(&state); + return (0); } + ret = TIFFjpeg_has_multiple_scans(&state); - /* Grab parameters that are same for all strips/tiles */ - sp->photometric = td->td_photometric; - switch (sp->photometric) { - case PHOTOMETRIC_YCBCR: - sp->h_sampling = td->td_ycbcrsubsampling[0]; - sp->v_sampling = td->td_ycbcrsubsampling[1]; - break; - default: - /* TIFF 6.0 forbids subsampling of all other color spaces */ - sp->h_sampling = 1; - sp->v_sampling = 1; - break; - } + TIFFjpeg_destroy(&state); - /* Set up for reading normal data */ - TIFFjpeg_data_src(sp, tif); - tif->tif_postdecode = _TIFFNoPostDecode; /* override byte swapping */ - return (1); + return ret; } /* * Set up for decoding a strip or tile. */ -static int +/*ARGSUSED*/ static int JPEGPreDecode(TIFF* tif, uint16 s) { - JPEGState *sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; - static const char module[] = "JPEGPreDecode"; - uint32 segment_width, segment_height; - int downsampled_output; - int ci; + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGPreDecode"; + uint32 segment_width, segment_height; + int downsampled_output; + int ci; - assert(sp != NULL); - - if (sp->cinfo.comm.is_decompressor == 0) - { - tif->tif_setupdecode( tif ); - } - - assert(sp->cinfo.comm.is_decompressor); - /* - * Reset decoder state from any previous strip/tile, - * in case application didn't read the whole strip. - */ - if (!TIFFjpeg_abort(sp)) - return (0); - /* - * Read the header for this strip/tile. - */ - - if (TIFFjpeg_read_header(sp, TRUE) != JPEG_HEADER_OK) - return (0); + assert(sp != NULL); + + if (sp->cinfo.comm.is_decompressor == 0) + { + tif->tif_setupdecode( tif ); + } + + assert(sp->cinfo.comm.is_decompressor); + /* + * Reset decoder state from any previous strip/tile, + * in case application didn't read the whole strip. + */ + if (!TIFFjpeg_abort(sp)) + return (0); + /* + * Read the header for this strip/tile. + */ + + if (TIFFjpeg_read_header(sp, TRUE) != JPEG_HEADER_OK) + return (0); tif->tif_rawcp = (uint8*) sp->src.next_input_byte; tif->tif_rawcc = sp->src.bytes_in_buffer; - /* - * Check image parameters and set decompression parameters. - */ - segment_width = td->td_imagewidth; - segment_height = td->td_imagelength - tif->tif_row; - if (isTiled(tif)) { + /* + * Check image parameters and set decompression parameters. + */ + if (isTiled(tif)) { segment_width = td->td_tilewidth; segment_height = td->td_tilelength; - sp->bytesperline = TIFFTileRowSize(tif); - } else { - if (segment_height > td->td_rowsperstrip) - segment_height = td->td_rowsperstrip; - sp->bytesperline = TIFFScanlineSize(tif); - } - if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { - /* - * For PC 2, scale down the expected strip/tile size - * to match a downsampled component - */ - segment_width = TIFFhowmany_32(segment_width, sp->h_sampling); - segment_height = TIFFhowmany_32(segment_height, sp->v_sampling); - } - if (sp->cinfo.d.image_width < segment_width || - sp->cinfo.d.image_height < segment_height) { - TIFFWarningExt(tif->tif_clientdata, module, - "Improper JPEG strip/tile size, " - "expected %dx%d, got %dx%d", - segment_width, segment_height, - sp->cinfo.d.image_width, - sp->cinfo.d.image_height); - } - if (sp->cinfo.d.image_width > segment_width || - sp->cinfo.d.image_height > segment_height) { - /* - * This case could be dangerous, if the strip or tile size has - * been reported as less than the amount of data jpeg will - * return, some potential security issues arise. Catch this - * case and error out. - */ - TIFFErrorExt(tif->tif_clientdata, module, - "JPEG strip/tile size exceeds expected dimensions," - " expected %dx%d, got %dx%d", - segment_width, segment_height, - sp->cinfo.d.image_width, sp->cinfo.d.image_height); - return (0); - } - if (sp->cinfo.d.num_components != - (td->td_planarconfig == PLANARCONFIG_CONTIG ? - td->td_samplesperpixel : 1)) { - TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG component count"); - return (0); - } + sp->bytesperline = TIFFTileRowSize(tif); + } else { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + sp->bytesperline = TIFFScanlineSize(tif); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { + /* + * For PC 2, scale down the expected strip/tile size + * to match a downsampled component + */ + segment_width = TIFFhowmany_32(segment_width, sp->h_sampling); + segment_height = TIFFhowmany_32(segment_height, sp->v_sampling); + } + if (sp->cinfo.d.image_width < segment_width || + sp->cinfo.d.image_height < segment_height) { + TIFFWarningExt(tif->tif_clientdata, module, + "Improper JPEG strip/tile size, " + "expected %dx%d, got %dx%d", + segment_width, segment_height, + sp->cinfo.d.image_width, + sp->cinfo.d.image_height); + } + if( sp->cinfo.d.image_width == segment_width && + sp->cinfo.d.image_height > segment_height && + tif->tif_row + segment_height == td->td_imagelength && + !isTiled(tif) ) { + /* Some files have a last strip, that should be truncated, */ + /* but their JPEG codestream has still the maximum strip */ + /* height. Warn about this as this is non compliant, but */ + /* we can safely recover from that. */ + TIFFWarningExt(tif->tif_clientdata, module, + "JPEG strip size exceeds expected dimensions," + " expected %dx%d, got %dx%d", + segment_width, segment_height, + sp->cinfo.d.image_width, sp->cinfo.d.image_height); + } + else if (sp->cinfo.d.image_width > segment_width || + sp->cinfo.d.image_height > segment_height) { + /* + * This case could be dangerous, if the strip or tile size has + * been reported as less than the amount of data jpeg will + * return, some potential security issues arise. Catch this + * case and error out. + */ + TIFFErrorExt(tif->tif_clientdata, module, + "JPEG strip/tile size exceeds expected dimensions," + " expected %dx%d, got %dx%d", + segment_width, segment_height, + sp->cinfo.d.image_width, sp->cinfo.d.image_height); + return (0); + } + if (sp->cinfo.d.num_components != + (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1)) { + TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG component count"); + return (0); + } #ifdef JPEG_LIB_MK1 - if (12 != td->td_bitspersample && 8 != td->td_bitspersample) { - TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision"); - return (0); - } - sp->cinfo.d.data_precision = td->td_bitspersample; - sp->cinfo.d.bits_in_jsample = td->td_bitspersample; + if (12 != td->td_bitspersample && 8 != td->td_bitspersample) { + TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision"); + return (0); + } + sp->cinfo.d.data_precision = td->td_bitspersample; + sp->cinfo.d.bits_in_jsample = td->td_bitspersample; #else - if (sp->cinfo.d.data_precision != td->td_bitspersample) { - TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision"); - return (0); - } + if (sp->cinfo.d.data_precision != td->td_bitspersample) { + TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision"); + return (0); + } #endif - if (td->td_planarconfig == PLANARCONFIG_CONTIG) { - /* Component 0 should have expected sampling factors */ - if (sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling || - sp->cinfo.d.comp_info[0].v_samp_factor != sp->v_sampling) { - TIFFErrorExt(tif->tif_clientdata, module, - "Improper JPEG sampling factors %d,%d\n" - "Apparently should be %d,%d.", - sp->cinfo.d.comp_info[0].h_samp_factor, - sp->cinfo.d.comp_info[0].v_samp_factor, - sp->h_sampling, sp->v_sampling); - return (0); - } - /* Rest should have sampling factors 1,1 */ - for (ci = 1; ci < sp->cinfo.d.num_components; ci++) { - if (sp->cinfo.d.comp_info[ci].h_samp_factor != 1 || - sp->cinfo.d.comp_info[ci].v_samp_factor != 1) { - TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG sampling factors"); - return (0); + + /* In some cases, libjpeg needs to allocate a lot of memory */ + /* http://www.libjpeg-turbo.org/pmwiki/uploads/About/TwoIssueswiththeJPEGStandard.pdf */ + if( TIFFjpeg_has_multiple_scans(sp) ) + { + /* In this case libjpeg will need to allocate memory or backing */ + /* store for all coefficients */ + /* See call to jinit_d_coef_controller() from master_selection() */ + /* in libjpeg */ + toff_t nRequiredMemory = (toff_t)sp->cinfo.d.image_width * + sp->cinfo.d.image_height * + sp->cinfo.d.num_components * + ((td->td_bitspersample+7)/8); + /* BLOCK_SMOOTHING_SUPPORTED is generally defined, so we need */ + /* to replicate the logic of jinit_d_coef_controller() */ + if( sp->cinfo.d.progressive_mode ) + nRequiredMemory *= 3; + +#ifndef TIFF_LIBJPEG_LARGEST_MEM_ALLOC +#define TIFF_LIBJPEG_LARGEST_MEM_ALLOC (100 * 1024 * 1024) +#endif + + if( nRequiredMemory > TIFF_LIBJPEG_LARGEST_MEM_ALLOC && + getenv("LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC") == NULL ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Reading this strip would require libjpeg to allocate " + "at least %u bytes. " + "This is disabled since above the %u threshold. " + "You may override this restriction by defining the " + "LIBTIFF_ALLOW_LARGE_LIBJPEG_MEM_ALLOC environment variable, " + "or recompile libtiff by defining the " + "TIFF_LIBJPEG_LARGEST_MEM_ALLOC macro to a value greater " + "than %u", + (unsigned)nRequiredMemory, + (unsigned)TIFF_LIBJPEG_LARGEST_MEM_ALLOC, + (unsigned)TIFF_LIBJPEG_LARGEST_MEM_ALLOC); + return (0); } } - } else { - /* PC 2's single component should have sampling factors 1,1 */ - if (sp->cinfo.d.comp_info[0].h_samp_factor != 1 || - sp->cinfo.d.comp_info[0].v_samp_factor != 1) { - TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG sampling factors"); - return (0); - } - } - downsampled_output = FALSE; - if (td->td_planarconfig == PLANARCONFIG_CONTIG && - sp->photometric == PHOTOMETRIC_YCBCR && - sp->jpegcolormode == JPEGCOLORMODE_RGB) { - /* Convert YCbCr to RGB */ - sp->cinfo.d.jpeg_color_space = JCS_YCbCr; - sp->cinfo.d.out_color_space = JCS_RGB; - } else { - /* Suppress colorspace handling */ - sp->cinfo.d.jpeg_color_space = JCS_UNKNOWN; - sp->cinfo.d.out_color_space = JCS_UNKNOWN; - if (td->td_planarconfig == PLANARCONFIG_CONTIG && - (sp->h_sampling != 1 || sp->v_sampling != 1)) - downsampled_output = TRUE; - /* XXX what about up-sampling? */ - } - if (downsampled_output) { - /* Need to use raw-data interface to libjpeg */ - sp->cinfo.d.raw_data_out = TRUE; - tif->tif_decoderow = DecodeRowError; - tif->tif_decodestrip = JPEGDecodeRaw; - tif->tif_decodetile = JPEGDecodeRaw; - } else { - /* Use normal interface to libjpeg */ - sp->cinfo.d.raw_data_out = FALSE; - tif->tif_decoderow = JPEGDecode; - tif->tif_decodestrip = JPEGDecode; - tif->tif_decodetile = JPEGDecode; - } - /* Start JPEG decompressor */ - if (!TIFFjpeg_start_decompress(sp)) - return (0); - /* Allocate downsampled-data buffers if needed */ - if (downsampled_output) { - if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info, - sp->cinfo.d.num_components)) - return (0); - sp->scancount = DCTSIZE; /* mark buffer empty */ - } - return (1); + + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + /* Component 0 should have expected sampling factors */ + if (sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling || + sp->cinfo.d.comp_info[0].v_samp_factor != sp->v_sampling) { + TIFFErrorExt(tif->tif_clientdata, module, + "Improper JPEG sampling factors %d,%d\n" + "Apparently should be %d,%d.", + sp->cinfo.d.comp_info[0].h_samp_factor, + sp->cinfo.d.comp_info[0].v_samp_factor, + sp->h_sampling, sp->v_sampling); + return (0); + } + /* Rest should have sampling factors 1,1 */ + for (ci = 1; ci < sp->cinfo.d.num_components; ci++) { + if (sp->cinfo.d.comp_info[ci].h_samp_factor != 1 || + sp->cinfo.d.comp_info[ci].v_samp_factor != 1) { + TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG sampling factors"); + return (0); + } + } + } else { + /* PC 2's single component should have sampling factors 1,1 */ + if (sp->cinfo.d.comp_info[0].h_samp_factor != 1 || + sp->cinfo.d.comp_info[0].v_samp_factor != 1) { + TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG sampling factors"); + return (0); + } + } + downsampled_output = FALSE; + if (td->td_planarconfig == PLANARCONFIG_CONTIG && + sp->photometric == PHOTOMETRIC_YCBCR && + sp->jpegcolormode == JPEGCOLORMODE_RGB) { + /* Convert YCbCr to RGB */ + sp->cinfo.d.jpeg_color_space = JCS_YCbCr; + sp->cinfo.d.out_color_space = JCS_RGB; + } else { + /* Suppress colorspace handling */ + sp->cinfo.d.jpeg_color_space = JCS_UNKNOWN; + sp->cinfo.d.out_color_space = JCS_UNKNOWN; + if (td->td_planarconfig == PLANARCONFIG_CONTIG && + (sp->h_sampling != 1 || sp->v_sampling != 1)) + downsampled_output = TRUE; + /* XXX what about up-sampling? */ + } + if (downsampled_output) { + /* Need to use raw-data interface to libjpeg */ + sp->cinfo.d.raw_data_out = TRUE; +#if JPEG_LIB_VERSION >= 70 + sp->cinfo.d.do_fancy_upsampling = FALSE; +#endif /* JPEG_LIB_VERSION >= 70 */ + tif->tif_decoderow = DecodeRowError; + tif->tif_decodestrip = JPEGDecodeRaw; + tif->tif_decodetile = JPEGDecodeRaw; + } else { + /* Use normal interface to libjpeg */ + sp->cinfo.d.raw_data_out = FALSE; + tif->tif_decoderow = JPEGDecode; + tif->tif_decodestrip = JPEGDecode; + tif->tif_decodetile = JPEGDecode; + } + /* Start JPEG decompressor */ + if (!TIFFjpeg_start_decompress(sp)) + return (0); + /* Allocate downsampled-data buffers if needed */ + if (downsampled_output) { + if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info, + sp->cinfo.d.num_components)) + return (0); + sp->scancount = DCTSIZE; /* mark buffer empty */ + } + return (1); } /* * Decode a chunk of pixels. * "Standard" case: returned data is not downsampled. */ -/*ARGSUSED*/ static int +#if !JPEG_LIB_MK1_OR_12BIT +static int JPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) { - JPEGState *sp = JState(tif); - tmsize_t nrows; - (void) s; + JPEGState *sp = JState(tif); + tmsize_t nrows; + (void) s; /* ** Update available information, buffer may have been refilled ** between decode requests */ - sp->src.next_input_byte = (const JOCTET*) tif->tif_rawcp; - sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc; + sp->src.next_input_byte = (const JOCTET*) tif->tif_rawcp; + sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc; if( sp->bytesperline == 0 ) return 0; + + nrows = cc / sp->bytesperline; + if (cc % sp->bytesperline) + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "fractional scanline not read"); - nrows = cc / sp->bytesperline; - if (cc % sp->bytesperline) - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline not read"); + if( nrows > (tmsize_t) sp->cinfo.d.image_height ) + nrows = sp->cinfo.d.image_height; - if( nrows > (tmsize_t) sp->cinfo.d.image_height ) - nrows = sp->cinfo.d.image_height; - - /* data is expected to be read in multiples of a scanline */ - if (nrows) - { - JSAMPROW line_work_buf = NULL; - - /* - * For 6B, only use temporary buffer for 12 bit imagery. - * For Mk1 always use it. - */ -#if !defined(JPEG_LIB_MK1) - if( sp->cinfo.d.data_precision == 12 ) -#endif + /* data is expected to be read in multiples of a scanline */ + if (nrows) { - line_work_buf = (JSAMPROW) - _TIFFmalloc(sizeof(short) * sp->cinfo.d.output_width - * sp->cinfo.d.num_components ); + do + { + /* + * In the libjpeg6b-9a 8bit case. We read directly into + * the TIFF buffer. + */ + JSAMPROW bufptr = (JSAMPROW)buf; + + if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1) + return (0); + + ++tif->tif_row; + buf += sp->bytesperline; + cc -= sp->bytesperline; + } while (--nrows > 0); } - do { - if( line_work_buf != NULL ) - { - /* - * In the MK1 case, we aways read into a 16bit buffer, and then - * pack down to 12bit or 8bit. In 6B case we only read into 16 - * bit buffer for 12bit data, which we need to repack. - */ - if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1) - return (0); - - if( sp->cinfo.d.data_precision == 12 ) - { - int value_pairs = (sp->cinfo.d.output_width - * sp->cinfo.d.num_components) / 2; - int iPair; - - for( iPair = 0; iPair < value_pairs; iPair++ ) - { - unsigned char *out_ptr = - ((unsigned char *) buf) + iPair * 3; - JSAMPLE *in_ptr = line_work_buf + iPair * 2; - - out_ptr[0] = (in_ptr[0] & 0xff0) >> 4; - out_ptr[1] = ((in_ptr[0] & 0xf) << 4) - | ((in_ptr[1] & 0xf00) >> 8); - out_ptr[2] = ((in_ptr[1] & 0xff) >> 0); - } - } - else if( sp->cinfo.d.data_precision == 8 ) - { - int value_count = (sp->cinfo.d.output_width - * sp->cinfo.d.num_components); - int iValue; - - for( iValue = 0; iValue < value_count; iValue++ ) - { - ((unsigned char *) buf)[iValue] = - line_work_buf[iValue] & 0xff; - } - } - } - else - { - /* - * In the libjpeg6b 8bit case. We read directly into the - * TIFF buffer. - */ - JSAMPROW bufptr = (JSAMPROW)buf; - - if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1) - return (0); - } - - ++tif->tif_row; - buf += sp->bytesperline; - cc -= sp->bytesperline; - } while (--nrows > 0); - - if( line_work_buf != NULL ) - _TIFFfree( line_work_buf ); - } - /* Update information on consumed data */ tif->tif_rawcp = (uint8*) sp->src.next_input_byte; tif->tif_rawcc = sp->src.bytes_in_buffer; - - /* Close down the decompressor if we've finished the strip or tile. */ - return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height - || TIFFjpeg_finish_decompress(sp); + + /* Close down the decompressor if we've finished the strip or tile. */ + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height + || TIFFjpeg_finish_decompress(sp); } +#endif /* !JPEG_LIB_MK1_OR_12BIT */ + +#if JPEG_LIB_MK1_OR_12BIT +/*ARGSUSED*/ static int +JPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) +{ + JPEGState *sp = JState(tif); + tmsize_t nrows; + (void) s; + + /* + ** Update available information, buffer may have been refilled + ** between decode requests + */ + sp->src.next_input_byte = (const JOCTET*) tif->tif_rawcp; + sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc; + + if( sp->bytesperline == 0 ) + return 0; + + nrows = cc / sp->bytesperline; + if (cc % sp->bytesperline) + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "fractional scanline not read"); + + if( nrows > (tmsize_t) sp->cinfo.d.image_height ) + nrows = sp->cinfo.d.image_height; + + /* data is expected to be read in multiples of a scanline */ + if (nrows) + { + JSAMPROW line_work_buf = NULL; + + /* + * For 6B, only use temporary buffer for 12 bit imagery. + * For Mk1 always use it. + */ + if( sp->cinfo.d.data_precision == 12 ) + { + line_work_buf = (JSAMPROW) + _TIFFmalloc(sizeof(short) * sp->cinfo.d.output_width + * sp->cinfo.d.num_components ); + } + + do + { + if( line_work_buf != NULL ) + { + /* + * In the MK1 case, we always read into a 16bit + * buffer, and then pack down to 12bit or 8bit. + * In 6B case we only read into 16 bit buffer + * for 12bit data, which we need to repack. + */ + if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1) + return (0); + + if( sp->cinfo.d.data_precision == 12 ) + { + int value_pairs = (sp->cinfo.d.output_width + * sp->cinfo.d.num_components) / 2; + int iPair; + + for( iPair = 0; iPair < value_pairs; iPair++ ) + { + unsigned char *out_ptr = + ((unsigned char *) buf) + iPair * 3; + JSAMPLE *in_ptr = line_work_buf + iPair * 2; + + out_ptr[0] = (unsigned char)((in_ptr[0] & 0xff0) >> 4); + out_ptr[1] = (unsigned char)(((in_ptr[0] & 0xf) << 4) + | ((in_ptr[1] & 0xf00) >> 8)); + out_ptr[2] = (unsigned char)(((in_ptr[1] & 0xff) >> 0)); + } + } + else if( sp->cinfo.d.data_precision == 8 ) + { + int value_count = (sp->cinfo.d.output_width + * sp->cinfo.d.num_components); + int iValue; + + for( iValue = 0; iValue < value_count; iValue++ ) + { + ((unsigned char *) buf)[iValue] = + line_work_buf[iValue] & 0xff; + } + } + } + + ++tif->tif_row; + buf += sp->bytesperline; + cc -= sp->bytesperline; + } while (--nrows > 0); + + if( line_work_buf != NULL ) + _TIFFfree( line_work_buf ); + } + + /* Update information on consumed data */ + tif->tif_rawcp = (uint8*) sp->src.next_input_byte; + tif->tif_rawcc = sp->src.bytes_in_buffer; + + /* Close down the decompressor if we've finished the strip or tile. */ + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height + || TIFFjpeg_finish_decompress(sp); +} +#endif /* JPEG_LIB_MK1_OR_12BIT */ /*ARGSUSED*/ static int DecodeRowError(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) @@ -1299,138 +1502,146 @@ DecodeRowError(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) /*ARGSUSED*/ static int JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) { - JPEGState *sp = JState(tif); - tmsize_t nrows; - (void) s; + JPEGState *sp = JState(tif); + tmsize_t nrows; + TIFFDirectory *td = &tif->tif_dir; + (void) s; - /* data is expected to be read in multiples of a scanline */ - if ( (nrows = sp->cinfo.d.image_height) ) { + nrows = sp->cinfo.d.image_height; + /* For last strip, limit number of rows to its truncated height */ + /* even if the codestream height is larger (which is not compliant, */ + /* but that we tolerate) */ + if( (uint32)nrows > td->td_imagelength - tif->tif_row && !isTiled(tif) ) + nrows = td->td_imagelength - tif->tif_row; - /* Cb,Cr both have sampling factors 1, so this is correct */ - JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width; - int samples_per_clump = sp->samplesperclump; + /* data is expected to be read in multiples of a scanline */ + if ( nrows != 0 ) { + + /* Cb,Cr both have sampling factors 1, so this is correct */ + JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width; + int samples_per_clump = sp->samplesperclump; #if defined(JPEG_LIB_MK1_OR_12BIT) - unsigned short* tmpbuf = _TIFFmalloc(sizeof(unsigned short) * - sp->cinfo.d.output_width * - sp->cinfo.d.num_components); - if(tmpbuf==NULL) { + unsigned short* tmpbuf = _TIFFmalloc(sizeof(unsigned short) * + sp->cinfo.d.output_width * + sp->cinfo.d.num_components); + if(tmpbuf==NULL) { TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw", - "Out of memory"); - return 0; + "Out of memory"); + return 0; } #endif - do { - jpeg_component_info *compptr; - int ci, clumpoffset; + do { + jpeg_component_info *compptr; + int ci, clumpoffset; if( cc < sp->bytesperline ) { - TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw", - "application buffer not large enough for all data."); - return 0; + TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw", + "application buffer not large enough for all data."); + return 0; } - /* Reload downsampled-data buffer if needed */ - if (sp->scancount >= DCTSIZE) { - int n = sp->cinfo.d.max_v_samp_factor * DCTSIZE; - if (TIFFjpeg_read_raw_data(sp, sp->ds_buffer, n) != n) - return (0); - sp->scancount = 0; - } - /* - * Fastest way to unseparate data is to make one pass - * over the scanline for each row of each component. - */ - clumpoffset = 0; /* first sample in clump */ - for (ci = 0, compptr = sp->cinfo.d.comp_info; - ci < sp->cinfo.d.num_components; - ci++, compptr++) { - int hsamp = compptr->h_samp_factor; - int vsamp = compptr->v_samp_factor; - int ypos; + /* Reload downsampled-data buffer if needed */ + if (sp->scancount >= DCTSIZE) { + int n = sp->cinfo.d.max_v_samp_factor * DCTSIZE; + if (TIFFjpeg_read_raw_data(sp, sp->ds_buffer, n) != n) + return (0); + sp->scancount = 0; + } + /* + * Fastest way to unseparate data is to make one pass + * over the scanline for each row of each component. + */ + clumpoffset = 0; /* first sample in clump */ + for (ci = 0, compptr = sp->cinfo.d.comp_info; + ci < sp->cinfo.d.num_components; + ci++, compptr++) { + int hsamp = compptr->h_samp_factor; + int vsamp = compptr->v_samp_factor; + int ypos; - for (ypos = 0; ypos < vsamp; ypos++) { - JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos]; - JDIMENSION nclump; + for (ypos = 0; ypos < vsamp; ypos++) { + JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos]; + JDIMENSION nclump; #if defined(JPEG_LIB_MK1_OR_12BIT) - JSAMPLE *outptr = (JSAMPLE*)tmpbuf + clumpoffset; + JSAMPLE *outptr = (JSAMPLE*)tmpbuf + clumpoffset; #else - JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset; - if (cc < clumpoffset + samples_per_clump*(clumps_per_line-1) + hsamp) { - TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw", - "application buffer not large enough for all data, possible subsampling issue"); - return 0; - } + JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset; + if (cc < (tmsize_t) (clumpoffset + samples_per_clump*(clumps_per_line-1) + hsamp)) { + TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw", + "application buffer not large enough for all data, possible subsampling issue"); + return 0; + } #endif - if (hsamp == 1) { - /* fast path for at least Cb and Cr */ - for (nclump = clumps_per_line; nclump-- > 0; ) { - outptr[0] = *inptr++; - outptr += samples_per_clump; - } - } else { - int xpos; + if (hsamp == 1) { + /* fast path for at least Cb and Cr */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + outptr[0] = *inptr++; + outptr += samples_per_clump; + } + } else { + int xpos; - /* general case */ - for (nclump = clumps_per_line; nclump-- > 0; ) { - for (xpos = 0; xpos < hsamp; xpos++) - outptr[xpos] = *inptr++; - outptr += samples_per_clump; - } - } - clumpoffset += hsamp; - } - } + /* general case */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + for (xpos = 0; xpos < hsamp; xpos++) + outptr[xpos] = *inptr++; + outptr += samples_per_clump; + } + } + clumpoffset += hsamp; + } + } #if defined(JPEG_LIB_MK1_OR_12BIT) - { - if (sp->cinfo.d.data_precision == 8) - { - int i=0; - int len = sp->cinfo.d.output_width * sp->cinfo.d.num_components; - for (i=0; icinfo.d.output_width - * sp->cinfo.d.num_components) / 2; - int iPair; - for( iPair = 0; iPair < value_pairs; iPair++ ) - { - unsigned char *out_ptr = ((unsigned char *) buf) + iPair * 3; - JSAMPLE *in_ptr = (JSAMPLE *) (tmpbuf + iPair * 2); - out_ptr[0] = (in_ptr[0] & 0xff0) >> 4; - out_ptr[1] = ((in_ptr[0] & 0xf) << 4) - | ((in_ptr[1] & 0xf00) >> 8); - out_ptr[2] = ((in_ptr[1] & 0xff) >> 0); - } - } - } + { + if (sp->cinfo.d.data_precision == 8) + { + int i=0; + int len = sp->cinfo.d.output_width * sp->cinfo.d.num_components; + for (i=0; icinfo.d.output_width + * sp->cinfo.d.num_components) / 2; + int iPair; + for( iPair = 0; iPair < value_pairs; iPair++ ) + { + unsigned char *out_ptr = ((unsigned char *) buf) + iPair * 3; + JSAMPLE *in_ptr = (JSAMPLE *) (tmpbuf + iPair * 2); + out_ptr[0] = (unsigned char)((in_ptr[0] & 0xff0) >> 4); + out_ptr[1] = (unsigned char)(((in_ptr[0] & 0xf) << 4) + | ((in_ptr[1] & 0xf00) >> 8)); + out_ptr[2] = (unsigned char)(((in_ptr[1] & 0xff) >> 0)); + } + } + } #endif - sp->scancount ++; - tif->tif_row += sp->v_sampling; + sp->scancount ++; + tif->tif_row += sp->v_sampling; - buf += sp->bytesperline; - cc -= sp->bytesperline; + buf += sp->bytesperline; + cc -= sp->bytesperline; - nrows -= sp->v_sampling; - } while (nrows > 0); + nrows -= sp->v_sampling; + } while (nrows > 0); #if defined(JPEG_LIB_MK1_OR_12BIT) - _TIFFfree(tmpbuf); + _TIFFfree(tmpbuf); #endif - } + } - /* Close down the decompressor if done. */ - return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height - || TIFFjpeg_finish_decompress(sp); + /* Close down the decompressor if done. */ + return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height + || TIFFjpeg_finish_decompress(sp); } @@ -1441,61 +1652,81 @@ JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) static void unsuppress_quant_table (JPEGState* sp, int tblno) { - JQUANT_TBL* qtbl; + JQUANT_TBL* qtbl; - if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL) - qtbl->sent_table = FALSE; + if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL) + qtbl->sent_table = FALSE; +} + +static void +suppress_quant_table (JPEGState* sp, int tblno) +{ + JQUANT_TBL* qtbl; + + if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL) + qtbl->sent_table = TRUE; } static void unsuppress_huff_table (JPEGState* sp, int tblno) { - JHUFF_TBL* htbl; + JHUFF_TBL* htbl; - if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL) - htbl->sent_table = FALSE; - if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL) - htbl->sent_table = FALSE; + if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = FALSE; + if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = FALSE; +} + +static void +suppress_huff_table (JPEGState* sp, int tblno) +{ + JHUFF_TBL* htbl; + + if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = TRUE; + if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL) + htbl->sent_table = TRUE; } static int prepare_JPEGTables(TIFF* tif) { - JPEGState* sp = JState(tif); + JPEGState* sp = JState(tif); - /* Initialize quant tables for current quality setting */ - if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE)) - return (0); - /* Mark only the tables we want for output */ - /* NB: chrominance tables are currently used only with YCbCr */ - if (!TIFFjpeg_suppress_tables(sp, TRUE)) - return (0); - if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) { - unsuppress_quant_table(sp, 0); - if (sp->photometric == PHOTOMETRIC_YCBCR) - unsuppress_quant_table(sp, 1); - } - if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) { - unsuppress_huff_table(sp, 0); - if (sp->photometric == PHOTOMETRIC_YCBCR) - unsuppress_huff_table(sp, 1); - } - /* Direct libjpeg output into jpegtables */ - if (!TIFFjpeg_tables_dest(sp, tif)) - return (0); - /* Emit tables-only datastream */ - if (!TIFFjpeg_write_tables(sp)) - return (0); + /* Initialize quant tables for current quality setting */ + if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE)) + return (0); + /* Mark only the tables we want for output */ + /* NB: chrominance tables are currently used only with YCbCr */ + if (!TIFFjpeg_suppress_tables(sp, TRUE)) + return (0); + if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) { + unsuppress_quant_table(sp, 0); + if (sp->photometric == PHOTOMETRIC_YCBCR) + unsuppress_quant_table(sp, 1); + } + if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) { + unsuppress_huff_table(sp, 0); + if (sp->photometric == PHOTOMETRIC_YCBCR) + unsuppress_huff_table(sp, 1); + } + /* Direct libjpeg output into jpegtables */ + if (!TIFFjpeg_tables_dest(sp, tif)) + return (0); + /* Emit tables-only datastream */ + if (!TIFFjpeg_write_tables(sp)) + return (0); - return (1); + return (1); } static int JPEGSetupEncode(TIFF* tif) { - JPEGState* sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; - static const char module[] = "JPEGSetupEncode"; + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGSetupEncode"; #if defined(JPEG_DUAL_MODE_8_12) && !defined(TIFFInitJPEG) if( tif->tif_dir.td_bitspersample == 12 ) @@ -1504,106 +1735,141 @@ JPEGSetupEncode(TIFF* tif) JPEGInitializeLibJPEG( tif, FALSE ); - assert(sp != NULL); - assert(!sp->cinfo.comm.is_decompressor); + assert(sp != NULL); + assert(!sp->cinfo.comm.is_decompressor); - /* - * Initialize all JPEG parameters to default values. - * Note that jpeg_set_defaults needs legal values for - * in_color_space and input_components. - */ - sp->cinfo.c.in_color_space = JCS_UNKNOWN; - sp->cinfo.c.input_components = 1; - if (!TIFFjpeg_set_defaults(sp)) - return (0); - /* Set per-file parameters */ - sp->photometric = td->td_photometric; - switch (sp->photometric) { - case PHOTOMETRIC_YCBCR: - sp->h_sampling = td->td_ycbcrsubsampling[0]; - sp->v_sampling = td->td_ycbcrsubsampling[1]; - /* - * A ReferenceBlackWhite field *must* be present since the - * default value is inappropriate for YCbCr. Fill in the - * proper value if application didn't set it. - */ - { - float *ref; - if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE, - &ref)) { - float refbw[6]; - long top = 1L << td->td_bitspersample; - refbw[0] = 0; - refbw[1] = (float)(top-1L); - refbw[2] = (float)(top>>1); - refbw[3] = refbw[1]; - refbw[4] = refbw[2]; - refbw[5] = refbw[1]; - TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE, - refbw); - } - } - break; - case PHOTOMETRIC_PALETTE: /* disallowed by Tech Note */ - case PHOTOMETRIC_MASK: - TIFFErrorExt(tif->tif_clientdata, module, - "PhotometricInterpretation %d not allowed for JPEG", - (int) sp->photometric); - return (0); - default: - /* TIFF 6.0 forbids subsampling of all other color spaces */ - sp->h_sampling = 1; - sp->v_sampling = 1; - break; - } + sp->photometric = td->td_photometric; - /* Verify miscellaneous parameters */ + /* + * Initialize all JPEG parameters to default values. + * Note that jpeg_set_defaults needs legal values for + * in_color_space and input_components. + */ + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + sp->cinfo.c.input_components = td->td_samplesperpixel; + if (sp->photometric == PHOTOMETRIC_YCBCR) { + if (sp->jpegcolormode == JPEGCOLORMODE_RGB) { + sp->cinfo.c.in_color_space = JCS_RGB; + } else { + sp->cinfo.c.in_color_space = JCS_YCbCr; + } + } else { + if ((td->td_photometric == PHOTOMETRIC_MINISWHITE || td->td_photometric == PHOTOMETRIC_MINISBLACK) && td->td_samplesperpixel == 1) + sp->cinfo.c.in_color_space = JCS_GRAYSCALE; + else if (td->td_photometric == PHOTOMETRIC_RGB && td->td_samplesperpixel == 3) + sp->cinfo.c.in_color_space = JCS_RGB; + else if (td->td_photometric == PHOTOMETRIC_SEPARATED && td->td_samplesperpixel == 4) + sp->cinfo.c.in_color_space = JCS_CMYK; + else + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + } + } else { + sp->cinfo.c.input_components = 1; + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + } + if (!TIFFjpeg_set_defaults(sp)) + return (0); + /* Set per-file parameters */ + switch (sp->photometric) { + case PHOTOMETRIC_YCBCR: + sp->h_sampling = td->td_ycbcrsubsampling[0]; + sp->v_sampling = td->td_ycbcrsubsampling[1]; + if( sp->h_sampling == 0 || sp->v_sampling == 0 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Invalig horizontal/vertical sampling value"); + return (0); + } + if( td->td_bitspersample > 16 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "BitsPerSample %d not allowed for JPEG", + td->td_bitspersample); + return (0); + } - /* - * This would need work if libtiff ever supports different - * depths for different components, or if libjpeg ever supports - * run-time selection of depth. Neither is imminent. - */ + /* + * A ReferenceBlackWhite field *must* be present since the + * default value is inappropriate for YCbCr. Fill in the + * proper value if application didn't set it. + */ + { + float *ref; + if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE, + &ref)) { + float refbw[6]; + long top = 1L << td->td_bitspersample; + refbw[0] = 0; + refbw[1] = (float)(top-1L); + refbw[2] = (float)(top>>1); + refbw[3] = refbw[1]; + refbw[4] = refbw[2]; + refbw[5] = refbw[1]; + TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE, + refbw); + } + } + break; + case PHOTOMETRIC_PALETTE: /* disallowed by Tech Note */ + case PHOTOMETRIC_MASK: + TIFFErrorExt(tif->tif_clientdata, module, + "PhotometricInterpretation %d not allowed for JPEG", + (int) sp->photometric); + return (0); + default: + /* TIFF 6.0 forbids subsampling of all other color spaces */ + sp->h_sampling = 1; + sp->v_sampling = 1; + break; + } + + /* Verify miscellaneous parameters */ + + /* + * This would need work if libtiff ever supports different + * depths for different components, or if libjpeg ever supports + * run-time selection of depth. Neither is imminent. + */ #ifdef JPEG_LIB_MK1 /* BITS_IN_JSAMPLE now permits 8 and 12 --- dgilbert */ - if (td->td_bitspersample != 8 && td->td_bitspersample != 12) + if (td->td_bitspersample != 8 && td->td_bitspersample != 12) #else - if (td->td_bitspersample != BITS_IN_JSAMPLE ) + if (td->td_bitspersample != BITS_IN_JSAMPLE ) #endif - { - TIFFErrorExt(tif->tif_clientdata, module, "BitsPerSample %d not allowed for JPEG", - (int) td->td_bitspersample); - return (0); - } - sp->cinfo.c.data_precision = td->td_bitspersample; + { + TIFFErrorExt(tif->tif_clientdata, module, "BitsPerSample %d not allowed for JPEG", + (int) td->td_bitspersample); + return (0); + } + sp->cinfo.c.data_precision = td->td_bitspersample; #ifdef JPEG_LIB_MK1 sp->cinfo.c.bits_in_jsample = td->td_bitspersample; #endif - if (isTiled(tif)) { - if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "JPEG tile height must be multiple of %d", - sp->v_sampling * DCTSIZE); - return (0); - } - if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "JPEG tile width must be multiple of %d", - sp->h_sampling * DCTSIZE); - return (0); - } - } else { - if (td->td_rowsperstrip < td->td_imagelength && - (td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "RowsPerStrip must be multiple of %d for JPEG", - sp->v_sampling * DCTSIZE); - return (0); - } - } + if (isTiled(tif)) { + if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "JPEG tile height must be multiple of %d", + sp->v_sampling * DCTSIZE); + return (0); + } + if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "JPEG tile width must be multiple of %d", + sp->h_sampling * DCTSIZE); + return (0); + } + } else { + if (td->td_rowsperstrip < td->td_imagelength && + (td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "RowsPerStrip must be multiple of %d for JPEG", + sp->v_sampling * DCTSIZE); + return (0); + } + } - /* Create a JPEGTables field if appropriate */ - if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF)) { + /* Create a JPEGTables field if appropriate */ + if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF)) { if( sp->jpegtables == NULL || memcmp(sp->jpegtables,"\0\0\0\0\0\0\0\0\0",8) == 0 ) { @@ -1614,16 +1880,16 @@ JPEGSetupEncode(TIFF* tif) tif->tif_flags |= TIFF_DIRTYDIRECT; TIFFSetFieldBit(tif, FIELD_JPEGTABLES); } - } else { - /* We do not support application-supplied JPEGTables, */ - /* so mark the field not present */ - TIFFClrFieldBit(tif, FIELD_JPEGTABLES); - } + } else { + /* We do not support application-supplied JPEGTables, */ + /* so mark the field not present */ + TIFFClrFieldBit(tif, FIELD_JPEGTABLES); + } - /* Direct libjpeg output to libtiff's output buffer */ - TIFFjpeg_data_dest(sp, tif); + /* Direct libjpeg output to libtiff's output buffer */ + TIFFjpeg_data_dest(sp, tif); - return (1); + return (1); } /* @@ -1632,131 +1898,134 @@ JPEGSetupEncode(TIFF* tif) static int JPEGPreEncode(TIFF* tif, uint16 s) { - JPEGState *sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; - static const char module[] = "JPEGPreEncode"; - uint32 segment_width, segment_height; - int downsampled_input; + JPEGState *sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "JPEGPreEncode"; + uint32 segment_width, segment_height; + int downsampled_input; - assert(sp != NULL); + assert(sp != NULL); + + if (sp->cinfo.comm.is_decompressor == 1) + { + tif->tif_setupencode( tif ); + } + + assert(!sp->cinfo.comm.is_decompressor); + /* + * Set encoding parameters for this strip/tile. + */ + if (isTiled(tif)) { + segment_width = td->td_tilewidth; + segment_height = td->td_tilelength; + sp->bytesperline = TIFFTileRowSize(tif); + } else { + segment_width = td->td_imagewidth; + segment_height = td->td_imagelength - tif->tif_row; + if (segment_height > td->td_rowsperstrip) + segment_height = td->td_rowsperstrip; + sp->bytesperline = TIFFScanlineSize(tif); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { + /* for PC 2, scale down the strip/tile size + * to match a downsampled component + */ + segment_width = TIFFhowmany_32(segment_width, sp->h_sampling); + segment_height = TIFFhowmany_32(segment_height, sp->v_sampling); + } + if (segment_width > 65535 || segment_height > 65535) { + TIFFErrorExt(tif->tif_clientdata, module, "Strip/tile too large for JPEG"); + return (0); + } + sp->cinfo.c.image_width = segment_width; + sp->cinfo.c.image_height = segment_height; + downsampled_input = FALSE; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + sp->cinfo.c.input_components = td->td_samplesperpixel; + if (sp->photometric == PHOTOMETRIC_YCBCR) { + if (sp->jpegcolormode != JPEGCOLORMODE_RGB) { + if (sp->h_sampling != 1 || sp->v_sampling != 1) + downsampled_input = TRUE; + } + if (!TIFFjpeg_set_colorspace(sp, JCS_YCbCr)) + return (0); + /* + * Set Y sampling factors; + * we assume jpeg_set_colorspace() set the rest to 1 + */ + sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling; + sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling; + } else { + if (!TIFFjpeg_set_colorspace(sp, sp->cinfo.c.in_color_space)) + return (0); + /* jpeg_set_colorspace set all sampling factors to 1 */ + } + } else { + if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN)) + return (0); + sp->cinfo.c.comp_info[0].component_id = s; + /* jpeg_set_colorspace() set sampling factors to 1 */ + if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) { + sp->cinfo.c.comp_info[0].quant_tbl_no = 1; + sp->cinfo.c.comp_info[0].dc_tbl_no = 1; + sp->cinfo.c.comp_info[0].ac_tbl_no = 1; + } + } + /* ensure libjpeg won't write any extraneous markers */ + sp->cinfo.c.write_JFIF_header = FALSE; + sp->cinfo.c.write_Adobe_marker = FALSE; + /* set up table handling correctly */ + /* calling TIFFjpeg_set_quality() causes quantization tables to be flagged */ + /* as being to be emitted, which we don't want in the JPEGTABLESMODE_QUANT */ + /* mode, so we must manually suppress them. However TIFFjpeg_set_quality() */ + /* should really be called when dealing with files with directories with */ + /* mixed qualities. see http://trac.osgeo.org/gdal/ticket/3539 */ + if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE)) + return (0); + if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) { + suppress_quant_table(sp, 0); + suppress_quant_table(sp, 1); + } + else { + unsuppress_quant_table(sp, 0); + unsuppress_quant_table(sp, 1); + } + if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) + { + /* Explicit suppression is only needed if we did not go through the */ + /* prepare_JPEGTables() code path, which may be the case if updating */ + /* an existing file */ + suppress_huff_table(sp, 0); + suppress_huff_table(sp, 1); + sp->cinfo.c.optimize_coding = FALSE; + } + else + sp->cinfo.c.optimize_coding = TRUE; + if (downsampled_input) { + /* Need to use raw-data interface to libjpeg */ + sp->cinfo.c.raw_data_in = TRUE; + tif->tif_encoderow = JPEGEncodeRaw; + tif->tif_encodestrip = JPEGEncodeRaw; + tif->tif_encodetile = JPEGEncodeRaw; + } else { + /* Use normal interface to libjpeg */ + sp->cinfo.c.raw_data_in = FALSE; + tif->tif_encoderow = JPEGEncode; + tif->tif_encodestrip = JPEGEncode; + tif->tif_encodetile = JPEGEncode; + } + /* Start JPEG compressor */ + if (!TIFFjpeg_start_compress(sp, FALSE)) + return (0); + /* Allocate downsampled-data buffers if needed */ + if (downsampled_input) { + if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info, + sp->cinfo.c.num_components)) + return (0); + } + sp->scancount = 0; - if (sp->cinfo.comm.is_decompressor == 1) - { - tif->tif_setupencode( tif ); - } - - assert(!sp->cinfo.comm.is_decompressor); - /* - * Set encoding parameters for this strip/tile. - */ - if (isTiled(tif)) { - segment_width = td->td_tilewidth; - segment_height = td->td_tilelength; - sp->bytesperline = TIFFTileRowSize(tif); - } else { - segment_width = td->td_imagewidth; - segment_height = td->td_imagelength - tif->tif_row; - if (segment_height > td->td_rowsperstrip) - segment_height = td->td_rowsperstrip; - sp->bytesperline = TIFFScanlineSize(tif); - } - if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) { - /* for PC 2, scale down the strip/tile size - * to match a downsampled component - */ - segment_width = TIFFhowmany_32(segment_width, sp->h_sampling); - segment_height = TIFFhowmany_32(segment_height, sp->v_sampling); - } - if (segment_width > 65535 || segment_height > 65535) { - TIFFErrorExt(tif->tif_clientdata, module, "Strip/tile too large for JPEG"); - return (0); - } - sp->cinfo.c.image_width = segment_width; - sp->cinfo.c.image_height = segment_height; - downsampled_input = FALSE; - if (td->td_planarconfig == PLANARCONFIG_CONTIG) { - sp->cinfo.c.input_components = td->td_samplesperpixel; - if (sp->photometric == PHOTOMETRIC_YCBCR) { - if (sp->jpegcolormode == JPEGCOLORMODE_RGB) { - sp->cinfo.c.in_color_space = JCS_RGB; - } else { - sp->cinfo.c.in_color_space = JCS_YCbCr; - if (sp->h_sampling != 1 || sp->v_sampling != 1) - downsampled_input = TRUE; - } - if (!TIFFjpeg_set_colorspace(sp, JCS_YCbCr)) - return (0); - /* - * Set Y sampling factors; - * we assume jpeg_set_colorspace() set the rest to 1 - */ - sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling; - sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling; - } else { - if ((td->td_photometric == PHOTOMETRIC_MINISWHITE || td->td_photometric == PHOTOMETRIC_MINISBLACK) && td->td_samplesperpixel == 1) - sp->cinfo.c.in_color_space = JCS_GRAYSCALE; - else if (td->td_photometric == PHOTOMETRIC_RGB) - sp->cinfo.c.in_color_space = JCS_RGB; - else if (td->td_photometric == PHOTOMETRIC_SEPARATED && td->td_samplesperpixel == 4) - sp->cinfo.c.in_color_space = JCS_CMYK; - else - sp->cinfo.c.in_color_space = JCS_UNKNOWN; - if (!TIFFjpeg_set_colorspace(sp, sp->cinfo.c.in_color_space)) - return (0); - /* jpeg_set_colorspace set all sampling factors to 1 */ - } - } else { - sp->cinfo.c.input_components = 1; - sp->cinfo.c.in_color_space = JCS_UNKNOWN; - if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN)) - return (0); - sp->cinfo.c.comp_info[0].component_id = s; - /* jpeg_set_colorspace() set sampling factors to 1 */ - if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) { - sp->cinfo.c.comp_info[0].quant_tbl_no = 1; - sp->cinfo.c.comp_info[0].dc_tbl_no = 1; - sp->cinfo.c.comp_info[0].ac_tbl_no = 1; - } - } - /* ensure libjpeg won't write any extraneous markers */ - sp->cinfo.c.write_JFIF_header = FALSE; - sp->cinfo.c.write_Adobe_marker = FALSE; - /* set up table handling correctly */ - if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE)) - return (0); - if (! (sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) { - unsuppress_quant_table(sp, 0); - unsuppress_quant_table(sp, 1); - } - if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) - sp->cinfo.c.optimize_coding = FALSE; - else - sp->cinfo.c.optimize_coding = TRUE; - if (downsampled_input) { - /* Need to use raw-data interface to libjpeg */ - sp->cinfo.c.raw_data_in = TRUE; - tif->tif_encoderow = JPEGEncodeRaw; - tif->tif_encodestrip = JPEGEncodeRaw; - tif->tif_encodetile = JPEGEncodeRaw; - } else { - /* Use normal interface to libjpeg */ - sp->cinfo.c.raw_data_in = FALSE; - tif->tif_encoderow = JPEGEncode; - tif->tif_encodestrip = JPEGEncode; - tif->tif_encodetile = JPEGEncode; - } - /* Start JPEG compressor */ - if (!TIFFjpeg_start_compress(sp, FALSE)) - return (0); - /* Allocate downsampled-data buffers if needed */ - if (downsampled_input) { - if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info, - sp->cinfo.c.num_components)) - return (0); - } - sp->scancount = 0; - - return (1); + return (1); } /* @@ -1766,18 +2035,18 @@ JPEGPreEncode(TIFF* tif, uint16 s) static int JPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) { - JPEGState *sp = JState(tif); - tmsize_t nrows; - JSAMPROW bufptr[1]; + JPEGState *sp = JState(tif); + tmsize_t nrows; + JSAMPROW bufptr[1]; short *line16 = NULL; int line16_count = 0; - (void) s; - assert(sp != NULL); - /* data is expected to be supplied in multiples of a scanline */ - nrows = cc / sp->bytesperline; - if (cc % sp->bytesperline) - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + (void) s; + assert(sp != NULL); + /* data is expected to be supplied in multiples of a scanline */ + nrows = cc / sp->bytesperline; + if (cc % sp->bytesperline) + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline discarded"); /* The last strip will be limited to image size */ @@ -1786,12 +2055,19 @@ JPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) if( sp->cinfo.c.data_precision == 12 ) { - line16_count = (sp->bytesperline * 2) / 3; + line16_count = (int)((sp->bytesperline * 2) / 3); line16 = (short *) _TIFFmalloc(sizeof(short) * line16_count); - // FIXME: undiagnosed malloc failure - } + if (!line16) + { + TIFFErrorExt(tif->tif_clientdata, + "JPEGEncode", + "Failed to allocate memory"); - while (nrows-- > 0) { + return 0; + } + } + + while (nrows-- > 0) { if( sp->cinfo.c.data_precision == 12 ) { @@ -1799,7 +2075,7 @@ JPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) int value_pairs = line16_count / 2; int iPair; - bufptr[0] = (JSAMPROW) line16; + bufptr[0] = (JSAMPROW) line16; for( iPair = 0; iPair < value_pairs; iPair++ ) { @@ -1813,21 +2089,21 @@ JPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) } else { - bufptr[0] = (JSAMPROW) buf; + bufptr[0] = (JSAMPROW) buf; } if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1) return (0); if (nrows > 0) tif->tif_row++; buf += sp->bytesperline; - } + } if( sp->cinfo.c.data_precision == 12 ) { _TIFFfree( line16 ); } - - return (1); + + return (1); } /* @@ -1837,82 +2113,82 @@ JPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) static int JPEGEncodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) { - JPEGState *sp = JState(tif); - JSAMPLE* inptr; - JSAMPLE* outptr; - tmsize_t nrows; - JDIMENSION clumps_per_line, nclump; - int clumpoffset, ci, xpos, ypos; - jpeg_component_info* compptr; - int samples_per_clump = sp->samplesperclump; - tmsize_t bytesperclumpline; + JPEGState *sp = JState(tif); + JSAMPLE* inptr; + JSAMPLE* outptr; + tmsize_t nrows; + JDIMENSION clumps_per_line, nclump; + int clumpoffset, ci, xpos, ypos; + jpeg_component_info* compptr; + int samples_per_clump = sp->samplesperclump; + tmsize_t bytesperclumpline; - (void) s; - assert(sp != NULL); - /* data is expected to be supplied in multiples of a clumpline */ - /* a clumpline is equivalent to v_sampling desubsampled scanlines */ - /* TODO: the following calculation of bytesperclumpline, should substitute calculation of sp->bytesperline, except that it is per v_sampling lines */ - bytesperclumpline = (((sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling) - *(sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7) - /8; + (void) s; + assert(sp != NULL); + /* data is expected to be supplied in multiples of a clumpline */ + /* a clumpline is equivalent to v_sampling desubsampled scanlines */ + /* TODO: the following calculation of bytesperclumpline, should substitute calculation of sp->bytesperline, except that it is per v_sampling lines */ + bytesperclumpline = (((sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling) + *(sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7) + /8; - nrows = ( cc / bytesperclumpline ) * sp->v_sampling; - if (cc % bytesperclumpline) - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline discarded"); + nrows = ( cc / bytesperclumpline ) * sp->v_sampling; + if (cc % bytesperclumpline) + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline discarded"); - /* Cb,Cr both have sampling factors 1, so this is correct */ - clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width; + /* Cb,Cr both have sampling factors 1, so this is correct */ + clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width; - while (nrows > 0) { - /* - * Fastest way to separate the data is to make one pass - * over the scanline for each row of each component. - */ - clumpoffset = 0; /* first sample in clump */ - for (ci = 0, compptr = sp->cinfo.c.comp_info; - ci < sp->cinfo.c.num_components; - ci++, compptr++) { - int hsamp = compptr->h_samp_factor; - int vsamp = compptr->v_samp_factor; - int padding = (int) (compptr->width_in_blocks * DCTSIZE - - clumps_per_line * hsamp); - for (ypos = 0; ypos < vsamp; ypos++) { - inptr = ((JSAMPLE*) buf) + clumpoffset; - outptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos]; - if (hsamp == 1) { - /* fast path for at least Cb and Cr */ - for (nclump = clumps_per_line; nclump-- > 0; ) { - *outptr++ = inptr[0]; - inptr += samples_per_clump; - } - } else { - /* general case */ - for (nclump = clumps_per_line; nclump-- > 0; ) { - for (xpos = 0; xpos < hsamp; xpos++) - *outptr++ = inptr[xpos]; - inptr += samples_per_clump; - } - } - /* pad each scanline as needed */ - for (xpos = 0; xpos < padding; xpos++) { - *outptr = outptr[-1]; - outptr++; - } - clumpoffset += hsamp; - } - } - sp->scancount++; - if (sp->scancount >= DCTSIZE) { - int n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; - if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) - return (0); - sp->scancount = 0; - } - tif->tif_row += sp->v_sampling; - buf += bytesperclumpline; - nrows -= sp->v_sampling; - } - return (1); + while (nrows > 0) { + /* + * Fastest way to separate the data is to make one pass + * over the scanline for each row of each component. + */ + clumpoffset = 0; /* first sample in clump */ + for (ci = 0, compptr = sp->cinfo.c.comp_info; + ci < sp->cinfo.c.num_components; + ci++, compptr++) { + int hsamp = compptr->h_samp_factor; + int vsamp = compptr->v_samp_factor; + int padding = (int) (compptr->width_in_blocks * DCTSIZE - + clumps_per_line * hsamp); + for (ypos = 0; ypos < vsamp; ypos++) { + inptr = ((JSAMPLE*) buf) + clumpoffset; + outptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos]; + if (hsamp == 1) { + /* fast path for at least Cb and Cr */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + *outptr++ = inptr[0]; + inptr += samples_per_clump; + } + } else { + /* general case */ + for (nclump = clumps_per_line; nclump-- > 0; ) { + for (xpos = 0; xpos < hsamp; xpos++) + *outptr++ = inptr[xpos]; + inptr += samples_per_clump; + } + } + /* pad each scanline as needed */ + for (xpos = 0; xpos < padding; xpos++) { + *outptr = outptr[-1]; + outptr++; + } + clumpoffset += hsamp; + } + } + sp->scancount++; + if (sp->scancount >= DCTSIZE) { + int n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; + if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) + return (0); + sp->scancount = 0; + } + tif->tif_row += sp->v_sampling; + buf += bytesperclumpline; + nrows -= sp->v_sampling; + } + return (1); } /* @@ -1921,232 +2197,228 @@ JPEGEncodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) static int JPEGPostEncode(TIFF* tif) { - JPEGState *sp = JState(tif); + JPEGState *sp = JState(tif); - if (sp->scancount > 0) { - /* - * Need to emit a partial bufferload of downsampled data. - * Pad the data vertically. - */ - int ci, ypos, n; - jpeg_component_info* compptr; + if (sp->scancount > 0) { + /* + * Need to emit a partial bufferload of downsampled data. + * Pad the data vertically. + */ + int ci, ypos, n; + jpeg_component_info* compptr; - for (ci = 0, compptr = sp->cinfo.c.comp_info; - ci < sp->cinfo.c.num_components; - ci++, compptr++) { - int vsamp = compptr->v_samp_factor; - tmsize_t row_width = compptr->width_in_blocks * DCTSIZE - * sizeof(JSAMPLE); - for (ypos = sp->scancount * vsamp; - ypos < DCTSIZE * vsamp; ypos++) { - _TIFFmemcpy((void*)sp->ds_buffer[ci][ypos], - (void*)sp->ds_buffer[ci][ypos-1], - row_width); + for (ci = 0, compptr = sp->cinfo.c.comp_info; + ci < sp->cinfo.c.num_components; + ci++, compptr++) { + int vsamp = compptr->v_samp_factor; + tmsize_t row_width = compptr->width_in_blocks * DCTSIZE + * sizeof(JSAMPLE); + for (ypos = sp->scancount * vsamp; + ypos < DCTSIZE * vsamp; ypos++) { + _TIFFmemcpy((void*)sp->ds_buffer[ci][ypos], + (void*)sp->ds_buffer[ci][ypos-1], + row_width); - } - } - n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; - if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) - return (0); - } + } + } + n = sp->cinfo.c.max_v_samp_factor * DCTSIZE; + if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n) + return (0); + } - return (TIFFjpeg_finish_compress(JState(tif))); + return (TIFFjpeg_finish_compress(JState(tif))); } static void JPEGCleanup(TIFF* tif) { - JPEGState *sp = JState(tif); + JPEGState *sp = JState(tif); + + assert(sp != 0); - assert(sp != 0); - - tif->tif_tagmethods.vgetfield = sp->vgetparent; - tif->tif_tagmethods.vsetfield = sp->vsetparent; - tif->tif_tagmethods.printdir = sp->printdir; - - if( sp != NULL ) { + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; + tif->tif_tagmethods.printdir = sp->printdir; if( sp->cinfo_initialized ) - TIFFjpeg_destroy(sp); /* release libjpeg resources */ + TIFFjpeg_destroy(sp); /* release libjpeg resources */ if (sp->jpegtables) /* tag value */ - _TIFFfree(sp->jpegtables); - } - _TIFFfree(tif->tif_data); /* release local state */ - tif->tif_data = NULL; + _TIFFfree(sp->jpegtables); + _TIFFfree(tif->tif_data); /* release local state */ + tif->tif_data = NULL; - _TIFFSetDefaultCompressionState(tif); + _TIFFSetDefaultCompressionState(tif); } -static void +static void JPEGResetUpsampled( TIFF* tif ) { - JPEGState* sp = JState(tif); - TIFFDirectory* td = &tif->tif_dir; + JPEGState* sp = JState(tif); + TIFFDirectory* td = &tif->tif_dir; - /* - * Mark whether returned data is up-sampled or not so TIFFStripSize - * and TIFFTileSize return values that reflect the true amount of - * data. - */ - tif->tif_flags &= ~TIFF_UPSAMPLED; - if (td->td_planarconfig == PLANARCONFIG_CONTIG) { - if (td->td_photometric == PHOTOMETRIC_YCBCR && - sp->jpegcolormode == JPEGCOLORMODE_RGB) { - tif->tif_flags |= TIFF_UPSAMPLED; - } else { + /* + * Mark whether returned data is up-sampled or not so TIFFStripSize + * and TIFFTileSize return values that reflect the true amount of + * data. + */ + tif->tif_flags &= ~TIFF_UPSAMPLED; + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + if (td->td_photometric == PHOTOMETRIC_YCBCR && + sp->jpegcolormode == JPEGCOLORMODE_RGB) { + tif->tif_flags |= TIFF_UPSAMPLED; + } else { #ifdef notdef - if (td->td_ycbcrsubsampling[0] != 1 || - td->td_ycbcrsubsampling[1] != 1) - ; /* XXX what about up-sampling? */ + if (td->td_ycbcrsubsampling[0] != 1 || + td->td_ycbcrsubsampling[1] != 1) + ; /* XXX what about up-sampling? */ #endif - } - } + } + } - /* - * Must recalculate cached tile size in case sampling state changed. - * Should we really be doing this now if image size isn't set? - */ + /* + * Must recalculate cached tile size in case sampling state changed. + * Should we really be doing this now if image size isn't set? + */ if( tif->tif_tilesize > 0 ) - tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1); + tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1); if( tif->tif_scanlinesize > 0 ) - tif->tif_scanlinesize = TIFFScanlineSize(tif); + tif->tif_scanlinesize = TIFFScanlineSize(tif); } static int JPEGVSetField(TIFF* tif, uint32 tag, va_list ap) { - JPEGState* sp = JState(tif); - const TIFFField* fip; - uint32 v32; + JPEGState* sp = JState(tif); + const TIFFField* fip; + uint32 v32; - assert(sp != NULL); + assert(sp != NULL); - switch (tag) { - case TIFFTAG_JPEGTABLES: - v32 = (uint32) va_arg(ap, uint32); - if (v32 == 0) { - /* XXX */ - return (0); - } - _TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*), - (long) v32); - sp->jpegtables_length = v32; - TIFFSetFieldBit(tif, FIELD_JPEGTABLES); - break; - case TIFFTAG_JPEGQUALITY: - sp->jpegquality = (int) va_arg(ap, int); - return (1); /* pseudo tag */ - case TIFFTAG_JPEGCOLORMODE: - sp->jpegcolormode = (int) va_arg(ap, int); - JPEGResetUpsampled( tif ); - return (1); /* pseudo tag */ - case TIFFTAG_PHOTOMETRIC: - { - int ret_value = (*sp->vsetparent)(tif, tag, ap); - JPEGResetUpsampled( tif ); - return ret_value; - } - case TIFFTAG_JPEGTABLESMODE: - sp->jpegtablesmode = (int) va_arg(ap, int); - return (1); /* pseudo tag */ - case TIFFTAG_YCBCRSUBSAMPLING: - /* mark the fact that we have a real ycbcrsubsampling! */ - sp->ycbcrsampling_fetched = 1; - /* should we be recomputing upsampling info here? */ - return (*sp->vsetparent)(tif, tag, ap); - default: - return (*sp->vsetparent)(tif, tag, ap); - } + switch (tag) { + case TIFFTAG_JPEGTABLES: + v32 = (uint32) va_arg(ap, uint32); + if (v32 == 0) { + /* XXX */ + return (0); + } + _TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*), v32); + sp->jpegtables_length = v32; + TIFFSetFieldBit(tif, FIELD_JPEGTABLES); + break; + case TIFFTAG_JPEGQUALITY: + sp->jpegquality = (int) va_arg(ap, int); + return (1); /* pseudo tag */ + case TIFFTAG_JPEGCOLORMODE: + sp->jpegcolormode = (int) va_arg(ap, int); + JPEGResetUpsampled( tif ); + return (1); /* pseudo tag */ + case TIFFTAG_PHOTOMETRIC: + { + int ret_value = (*sp->vsetparent)(tif, tag, ap); + JPEGResetUpsampled( tif ); + return ret_value; + } + case TIFFTAG_JPEGTABLESMODE: + sp->jpegtablesmode = (int) va_arg(ap, int); + return (1); /* pseudo tag */ + case TIFFTAG_YCBCRSUBSAMPLING: + /* mark the fact that we have a real ycbcrsubsampling! */ + sp->ycbcrsampling_fetched = 1; + /* should we be recomputing upsampling info here? */ + return (*sp->vsetparent)(tif, tag, ap); + default: + return (*sp->vsetparent)(tif, tag, ap); + } - if ((fip = TIFFFieldWithTag(tif, tag))) { - TIFFSetFieldBit(tif, fip->field_bit); - } else { - return (0); - } + if ((fip = TIFFFieldWithTag(tif, tag)) != NULL) { + TIFFSetFieldBit(tif, fip->field_bit); + } else { + return (0); + } - tif->tif_flags |= TIFF_DIRTYDIRECT; - return (1); + tif->tif_flags |= TIFF_DIRTYDIRECT; + return (1); } static int JPEGVGetField(TIFF* tif, uint32 tag, va_list ap) { - JPEGState* sp = JState(tif); + JPEGState* sp = JState(tif); - assert(sp != NULL); + assert(sp != NULL); - switch (tag) { - case TIFFTAG_JPEGTABLES: - *va_arg(ap, uint32*) = sp->jpegtables_length; - *va_arg(ap, void**) = sp->jpegtables; - break; - case TIFFTAG_JPEGQUALITY: - *va_arg(ap, int*) = sp->jpegquality; - break; - case TIFFTAG_JPEGCOLORMODE: - *va_arg(ap, int*) = sp->jpegcolormode; - break; - case TIFFTAG_JPEGTABLESMODE: - *va_arg(ap, int*) = sp->jpegtablesmode; - break; - default: - return (*sp->vgetparent)(tif, tag, ap); - } - return (1); + switch (tag) { + case TIFFTAG_JPEGTABLES: + *va_arg(ap, uint32*) = sp->jpegtables_length; + *va_arg(ap, void**) = sp->jpegtables; + break; + case TIFFTAG_JPEGQUALITY: + *va_arg(ap, int*) = sp->jpegquality; + break; + case TIFFTAG_JPEGCOLORMODE: + *va_arg(ap, int*) = sp->jpegcolormode; + break; + case TIFFTAG_JPEGTABLESMODE: + *va_arg(ap, int*) = sp->jpegtablesmode; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); } static void JPEGPrintDir(TIFF* tif, FILE* fd, long flags) { - JPEGState* sp = JState(tif); + JPEGState* sp = JState(tif); - assert(sp != NULL); - (void) flags; + assert(sp != NULL); + (void) flags; if( sp != NULL ) { - if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) - fprintf(fd, " JPEG Tables: (%lu bytes)\n", - (unsigned long) sp->jpegtables_length); - if (sp->printdir) - (*sp->printdir)(tif, fd, flags); - } + if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) + fprintf(fd, " JPEG Tables: (%lu bytes)\n", + (unsigned long) sp->jpegtables_length); + if (sp->printdir) + (*sp->printdir)(tif, fd, flags); + } } static uint32 JPEGDefaultStripSize(TIFF* tif, uint32 s) { - JPEGState* sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; - s = (*sp->defsparent)(tif, s); - if (s < td->td_imagelength) - s = TIFFroundup_32(s, td->td_ycbcrsubsampling[1] * DCTSIZE); - return (s); + s = (*sp->defsparent)(tif, s); + if (s < td->td_imagelength) + s = TIFFroundup_32(s, td->td_ycbcrsubsampling[1] * DCTSIZE); + return (s); } static void JPEGDefaultTileSize(TIFF* tif, uint32* tw, uint32* th) { - JPEGState* sp = JState(tif); - TIFFDirectory *td = &tif->tif_dir; + JPEGState* sp = JState(tif); + TIFFDirectory *td = &tif->tif_dir; - (*sp->deftparent)(tif, tw, th); - *tw = TIFFroundup_32(*tw, td->td_ycbcrsubsampling[0] * DCTSIZE); - *th = TIFFroundup_32(*th, td->td_ycbcrsubsampling[1] * DCTSIZE); + (*sp->deftparent)(tif, tw, th); + *tw = TIFFroundup_32(*tw, td->td_ycbcrsubsampling[0] * DCTSIZE); + *th = TIFFroundup_32(*th, td->td_ycbcrsubsampling[1] * DCTSIZE); } /* * The JPEG library initialized used to be done in TIFFInitJPEG(), but * now that we allow a TIFF file to be opened in update mode it is necessary * to have some way of deciding whether compression or decompression is - * desired other than looking at tif->tif_mode. We accomplish this by + * desired other than looking at tif->tif_mode. We accomplish this by * examining {TILE/STRIP}BYTECOUNTS to see if there is a non-zero entry. - * If so, we assume decompression is desired. + * If so, we assume decompression is desired. * * This is tricky, because TIFFInitJPEG() is called while the directory is * being read, and generally speaking the BYTECOUNTS tag won't have been read * at that point. So we try to defer jpeg library initialization till we * do have that tag ... basically any access that might require the compressor - * or decompressor that occurs after the reading of the directory. + * or decompressor that occurs after the reading of the directory. * * In an ideal world compressors or decompressors would be setup * at the point where a single tile or strip was accessed (for read or write) @@ -2181,6 +2453,25 @@ static int JPEGInitializeLibJPEG( TIFF * tif, int decompress ) } else { if (!TIFFjpeg_create_compress(sp)) return (0); +#ifndef TIFF_JPEG_MAX_MEMORY_TO_USE +#define TIFF_JPEG_MAX_MEMORY_TO_USE (10 * 1024 * 1024) +#endif + /* libjpeg turbo 1.5.2 honours max_memory_to_use, but has no backing */ + /* store implementation, so better not set max_memory_to_use ourselves. */ + /* See https://github.com/libjpeg-turbo/libjpeg-turbo/issues/162 */ + if( sp->cinfo.c.mem->max_memory_to_use > 0 ) + { + /* This is to address bug related in ticket GDAL #1795. */ + if (getenv("JPEGMEM") == NULL) + { + /* Increase the max memory usable. This helps when creating files */ + /* with "big" tile, without using libjpeg temporary files. */ + /* For example a 512x512 tile with 3 bands */ + /* requires 1.5 MB which is above libjpeg 1MB default */ + if( sp->cinfo.c.mem->max_memory_to_use < TIFF_JPEG_MAX_MEMORY_TO_USE ) + sp->cinfo.c.mem->max_memory_to_use = TIFF_JPEG_MAX_MEMORY_TO_USE; + } + } } sp->cinfo_initialized = TRUE; @@ -2191,82 +2482,82 @@ static int JPEGInitializeLibJPEG( TIFF * tif, int decompress ) int TIFFInitJPEG(TIFF* tif, int scheme) { - JPEGState* sp; + JPEGState* sp; - assert(scheme == COMPRESSION_JPEG); + assert(scheme == COMPRESSION_JPEG); - /* - * Merge codec-specific tag information. - */ - if (!_TIFFMergeFields(tif, jpegFields, TIFFArrayCount(jpegFields))) { - TIFFErrorExt(tif->tif_clientdata, - "TIFFInitJPEG", - "Merging JPEG codec-specific tags failed"); - return 0; - } + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, jpegFields, TIFFArrayCount(jpegFields))) { + TIFFErrorExt(tif->tif_clientdata, + "TIFFInitJPEG", + "Merging JPEG codec-specific tags failed"); + return 0; + } - /* - * Allocate state block so tag methods have storage to record values. - */ - tif->tif_data = (uint8*) _TIFFmalloc(sizeof (JPEGState)); + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (uint8*) _TIFFmalloc(sizeof (JPEGState)); - if (tif->tif_data == NULL) { - TIFFErrorExt(tif->tif_clientdata, - "TIFFInitJPEG", "No space for JPEG state block"); - return 0; - } + if (tif->tif_data == NULL) { + TIFFErrorExt(tif->tif_clientdata, + "TIFFInitJPEG", "No space for JPEG state block"); + return 0; + } _TIFFmemset(tif->tif_data, 0, sizeof(JPEGState)); - sp = JState(tif); - sp->tif = tif; /* back link */ + sp = JState(tif); + sp->tif = tif; /* back link */ - /* - * Override parent get/set field methods. - */ - sp->vgetparent = tif->tif_tagmethods.vgetfield; - tif->tif_tagmethods.vgetfield = JPEGVGetField; /* hook for codec tags */ - sp->vsetparent = tif->tif_tagmethods.vsetfield; - tif->tif_tagmethods.vsetfield = JPEGVSetField; /* hook for codec tags */ - sp->printdir = tif->tif_tagmethods.printdir; - tif->tif_tagmethods.printdir = JPEGPrintDir; /* hook for codec tags */ + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = JPEGVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = JPEGVSetField; /* hook for codec tags */ + sp->printdir = tif->tif_tagmethods.printdir; + tif->tif_tagmethods.printdir = JPEGPrintDir; /* hook for codec tags */ - /* Default values for codec-specific fields */ - sp->jpegtables = NULL; - sp->jpegtables_length = 0; - sp->jpegquality = 75; /* Default IJG quality */ - sp->jpegcolormode = JPEGCOLORMODE_RAW; - sp->jpegtablesmode = JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF; + /* Default values for codec-specific fields */ + sp->jpegtables = NULL; + sp->jpegtables_length = 0; + sp->jpegquality = 75; /* Default IJG quality */ + sp->jpegcolormode = JPEGCOLORMODE_RAW; + sp->jpegtablesmode = JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF; sp->ycbcrsampling_fetched = 0; - /* - * Install codec methods. - */ - tif->tif_fixuptags = JPEGFixupTags; - tif->tif_setupdecode = JPEGSetupDecode; - tif->tif_predecode = JPEGPreDecode; - tif->tif_decoderow = JPEGDecode; - tif->tif_decodestrip = JPEGDecode; - tif->tif_decodetile = JPEGDecode; - tif->tif_setupencode = JPEGSetupEncode; - tif->tif_preencode = JPEGPreEncode; - tif->tif_postencode = JPEGPostEncode; - tif->tif_encoderow = JPEGEncode; - tif->tif_encodestrip = JPEGEncode; - tif->tif_encodetile = JPEGEncode; - tif->tif_cleanup = JPEGCleanup; - sp->defsparent = tif->tif_defstripsize; - tif->tif_defstripsize = JPEGDefaultStripSize; - sp->deftparent = tif->tif_deftilesize; - tif->tif_deftilesize = JPEGDefaultTileSize; - tif->tif_flags |= TIFF_NOBITREV; /* no bit reversal, please */ + /* + * Install codec methods. + */ + tif->tif_fixuptags = JPEGFixupTags; + tif->tif_setupdecode = JPEGSetupDecode; + tif->tif_predecode = JPEGPreDecode; + tif->tif_decoderow = JPEGDecode; + tif->tif_decodestrip = JPEGDecode; + tif->tif_decodetile = JPEGDecode; + tif->tif_setupencode = JPEGSetupEncode; + tif->tif_preencode = JPEGPreEncode; + tif->tif_postencode = JPEGPostEncode; + tif->tif_encoderow = JPEGEncode; + tif->tif_encodestrip = JPEGEncode; + tif->tif_encodetile = JPEGEncode; + tif->tif_cleanup = JPEGCleanup; + sp->defsparent = tif->tif_defstripsize; + tif->tif_defstripsize = JPEGDefaultStripSize; + sp->deftparent = tif->tif_deftilesize; + tif->tif_deftilesize = JPEGDefaultTileSize; + tif->tif_flags |= TIFF_NOBITREV; /* no bit reversal, please */ sp->cinfo_initialized = FALSE; - /* - ** Create a JPEGTables field if no directory has yet been created. + /* + ** Create a JPEGTables field if no directory has yet been created. ** We do this just to ensure that sufficient space is reserved for ** the JPEGTables field. It will be properly created the right - ** size later. + ** size later. */ if( tif->tif_diroff == 0 ) { @@ -2274,19 +2565,28 @@ TIFFInitJPEG(TIFF* tif, int scheme) /* The following line assumes incorrectly that all JPEG-in-TIFF files will have a JPEGTABLES tag generated and causes null-filled JPEGTABLES tags to be written -when the JPEG data is placed with TIFFWriteRawStrip. The field bit should be -set, anyway, later when actual JPEGTABLES header is generated, so removing it +when the JPEG data is placed with TIFFWriteRawStrip. The field bit should be +set, anyway, later when actual JPEGTABLES header is generated, so removing it here hopefully is harmless. TIFFSetFieldBit(tif, FIELD_JPEGTABLES); */ sp->jpegtables_length = SIZE_OF_JPEGTABLES; sp->jpegtables = (void *) _TIFFmalloc(sp->jpegtables_length); - // FIXME: NULL-deref after malloc failure - _TIFFmemset(sp->jpegtables, 0, SIZE_OF_JPEGTABLES); + if (sp->jpegtables) + { + _TIFFmemset(sp->jpegtables, 0, SIZE_OF_JPEGTABLES); + } + else + { + TIFFErrorExt(tif->tif_clientdata, + "TIFFInitJPEG", + "Failed to allocate memory for JPEG tables"); + return 0; + } #undef SIZE_OF_JPEGTABLES } - return 1; + return 1; } #endif /* JPEG_SUPPORT */ diff --git a/3rdparty/libtiff/tif_jpeg_12.c b/3rdparty/libtiff/tif_jpeg_12.c index 8ce2d1cd2e..b458c25899 100644 --- a/3rdparty/libtiff/tif_jpeg_12.c +++ b/3rdparty/libtiff/tif_jpeg_12.c @@ -4,6 +4,10 @@ #if defined(JPEG_DUAL_MODE_8_12) # define TIFFInitJPEG TIFFInitJPEG_12 +# define TIFFJPEGIsFullStripRequired TIFFJPEGIsFullStripRequired_12 + +int +TIFFInitJPEG_12(TIFF* tif, int scheme); # include LIBJPEG_12_PATH @@ -40,7 +44,7 @@ int TIFFReInitJPEG_12( TIFF *tif, int scheme, int is_encode ) tif->tif_postencode = JPEGPostEncode; tif->tif_encoderow = JPEGEncode; tif->tif_encodestrip = JPEGEncode; - tif->tif_encodetile = JPEGEncode; + tif->tif_encodetile = JPEGEncode; tif->tif_cleanup = JPEGCleanup; tif->tif_defstripsize = JPEGDefaultStripSize; tif->tif_deftilesize = JPEGDefaultTileSize; diff --git a/3rdparty/libtiff/tif_luv.c b/3rdparty/libtiff/tif_luv.c index 0ab06ff28d..4b25244bff 100644 --- a/3rdparty/libtiff/tif_luv.c +++ b/3rdparty/libtiff/tif_luv.c @@ -1,26 +1,26 @@ -/* $Id: tif_luv.c,v 1.35 2011-04-02 20:54:09 bfriesen Exp $ */ +/* $Id: tif_luv.c,v 1.49 2017-07-24 12:47:30 erouault Exp $ */ /* * Copyright (c) 1997 Greg Ward Larson * Copyright (c) 1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler, Greg Larson and Silicon Graphics may not be used in any * advertising or publicity relating to the software without the specific, * prior written permission of Sam Leffler, Greg Larson and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER, GREG LARSON OR SILICON GRAPHICS BE LIABLE * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -36,7 +36,7 @@ * LogLuv image support uses the TIFF library to store 16 or 10-bit * log luminance values with 8 bits each of u and v or a 14-bit index. * - * The codec can take as input and produce as output 32-bit IEEE float values + * The codec can take as input and produce as output 32-bit IEEE float values * as well as 16-bit integer values. A 16-bit luminance is interpreted * as a sign bit followed by a 15-bit integer that is converted * to and from a linear magnitude using the transformation: @@ -158,16 +158,17 @@ typedef struct logLuvState LogLuvState; struct logLuvState { - int user_datafmt; /* user data format */ - int encode_meth; /* encoding method */ - int pixel_size; /* bytes per pixel */ + int encoder_state; /* 1 if encoder correctly initialized */ + int user_datafmt; /* user data format */ + int encode_meth; /* encoding method */ + int pixel_size; /* bytes per pixel */ - uint8* tbuf; /* translation buffer */ - tmsize_t tbuflen; /* buffer length */ - void (*tfunc)(LogLuvState*, uint8*, tmsize_t); + uint8* tbuf; /* translation buffer */ + tmsize_t tbuflen; /* buffer length */ + void (*tfunc)(LogLuvState*, uint8*, tmsize_t); - TIFFVSetMethod vgetparent; /* super-class method */ - TIFFVSetMethod vsetparent; /* super-class method */ + TIFFVSetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ }; #define DecoderState(tif) ((LogLuvState*) (tif)->tif_data) @@ -183,67 +184,74 @@ struct logLuvState { static int LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) { - static const char module[] = "LogL16Decode"; - LogLuvState* sp = DecoderState(tif); - int shft; - tmsize_t i; - tmsize_t npixels; - unsigned char* bp; - int16* tp; - int16 b; - tmsize_t cc; - int rc; + static const char module[] = "LogL16Decode"; + LogLuvState* sp = DecoderState(tif); + int shft; + tmsize_t i; + tmsize_t npixels; + unsigned char* bp; + int16* tp; + int16 b; + tmsize_t cc; + int rc; - assert(s == 0); - assert(sp != NULL); + assert(s == 0); + assert(sp != NULL); - npixels = occ / sp->pixel_size; + npixels = occ / sp->pixel_size; - if (sp->user_datafmt == SGILOGDATAFMT_16BIT) - tp = (int16*) op; - else { - assert(sp->tbuflen >= npixels); - tp = (int16*) sp->tbuf; - } - _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0])); + if (sp->user_datafmt == SGILOGDATAFMT_16BIT) + tp = (int16*) op; + else { + if(sp->tbuflen < npixels) { + TIFFErrorExt(tif->tif_clientdata, module, + "Translation buffer too short"); + return (0); + } + tp = (int16*) sp->tbuf; + } + _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0])); - bp = (unsigned char*) tif->tif_rawcp; - cc = tif->tif_rawcc; - /* get each byte string */ - for (shft = 2*8; (shft -= 8) >= 0; ) { - for (i = 0; i < npixels && cc > 0; ) - if (*bp >= 128) { /* run */ - rc = *bp++ + (2-128); /* TODO: potential input buffer overrun when decoding corrupt or truncated data */ - b = (int16)(*bp++ << shft); - cc -= 2; - while (rc-- && i < npixels) - tp[i++] |= b; - } else { /* non-run */ - rc = *bp++; /* nul is noop */ - while (--cc && rc-- && i < npixels) - tp[i++] |= (int16)*bp++ << shft; - } - if (i != npixels) { + bp = (unsigned char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + /* get each byte string */ + for (shft = 2*8; (shft -= 8) >= 0; ) { + for (i = 0; i < npixels && cc > 0; ) { + if (*bp >= 128) { /* run */ + if( cc < 2 ) + break; + rc = *bp++ + (2-128); + b = (int16)(*bp++ << shft); + cc -= 2; + while (rc-- && i < npixels) + tp[i++] |= b; + } else { /* non-run */ + rc = *bp++; /* nul is noop */ + while (--cc && rc-- && i < npixels) + tp[i++] |= (int16)*bp++ << shft; + } + } + if (i != npixels) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at row %lu (short %I64d pixels)", - (unsigned long) tif->tif_row, - (unsigned __int64) (npixels - i)); + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at row %lu (short %I64d pixels)", + (unsigned long) tif->tif_row, + (unsigned __int64) (npixels - i)); #else - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at row %lu (short %llu pixels)", - (unsigned long) tif->tif_row, - (unsigned long long) (npixels - i)); + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at row %lu (short %llu pixels)", + (unsigned long) tif->tif_row, + (unsigned long long) (npixels - i)); #endif - tif->tif_rawcp = (uint8*) bp; - tif->tif_rawcc = cc; - return (0); - } - } - (*sp->tfunc)(sp, op, npixels); - tif->tif_rawcp = (uint8*) bp; - tif->tif_rawcc = cc; - return (1); + tif->tif_rawcp = (uint8*) bp; + tif->tif_rawcc = cc; + return (0); + } + } + (*sp->tfunc)(sp, op, npixels); + tif->tif_rawcp = (uint8*) bp; + tif->tif_rawcc = cc; + return (1); } /* @@ -252,51 +260,55 @@ LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) static int LogLuvDecode24(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) { - static const char module[] = "LogLuvDecode24"; - LogLuvState* sp = DecoderState(tif); - tmsize_t cc; - tmsize_t i; - tmsize_t npixels; - unsigned char* bp; - uint32* tp; + static const char module[] = "LogLuvDecode24"; + LogLuvState* sp = DecoderState(tif); + tmsize_t cc; + tmsize_t i; + tmsize_t npixels; + unsigned char* bp; + uint32* tp; - assert(s == 0); - assert(sp != NULL); + assert(s == 0); + assert(sp != NULL); - npixels = occ / sp->pixel_size; + npixels = occ / sp->pixel_size; - if (sp->user_datafmt == SGILOGDATAFMT_RAW) - tp = (uint32 *)op; - else { - assert(sp->tbuflen >= npixels); - tp = (uint32 *) sp->tbuf; - } - /* copy to array of uint32 */ - bp = (unsigned char*) tif->tif_rawcp; - cc = tif->tif_rawcc; - for (i = 0; i < npixels && cc > 0; i++) { - tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2]; - bp += 3; - cc -= 3; - } - tif->tif_rawcp = (uint8*) bp; - tif->tif_rawcc = cc; - if (i != npixels) { + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32 *)op; + else { + if(sp->tbuflen < npixels) { + TIFFErrorExt(tif->tif_clientdata, module, + "Translation buffer too short"); + return (0); + } + tp = (uint32 *) sp->tbuf; + } + /* copy to array of uint32 */ + bp = (unsigned char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + for (i = 0; i < npixels && cc >= 3; i++) { + tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2]; + bp += 3; + cc -= 3; + } + tif->tif_rawcp = (uint8*) bp; + tif->tif_rawcc = cc; + if (i != npixels) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at row %lu (short %I64d pixels)", - (unsigned long) tif->tif_row, - (unsigned __int64) (npixels - i)); + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at row %lu (short %I64d pixels)", + (unsigned long) tif->tif_row, + (unsigned __int64) (npixels - i)); #else - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at row %lu (short %llu pixels)", - (unsigned long) tif->tif_row, - (unsigned long long) (npixels - i)); + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at row %lu (short %llu pixels)", + (unsigned long) tif->tif_row, + (unsigned long long) (npixels - i)); #endif - return (0); - } - (*sp->tfunc)(sp, op, npixels); - return (1); + return (0); + } + (*sp->tfunc)(sp, op, npixels); + return (1); } /* @@ -305,68 +317,75 @@ LogLuvDecode24(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) static int LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) { - static const char module[] = "LogLuvDecode32"; - LogLuvState* sp; - int shft; - tmsize_t i; - tmsize_t npixels; - unsigned char* bp; - uint32* tp; - uint32 b; - tmsize_t cc; - int rc; + static const char module[] = "LogLuvDecode32"; + LogLuvState* sp; + int shft; + tmsize_t i; + tmsize_t npixels; + unsigned char* bp; + uint32* tp; + uint32 b; + tmsize_t cc; + int rc; - assert(s == 0); - sp = DecoderState(tif); - assert(sp != NULL); + assert(s == 0); + sp = DecoderState(tif); + assert(sp != NULL); - npixels = occ / sp->pixel_size; + npixels = occ / sp->pixel_size; - if (sp->user_datafmt == SGILOGDATAFMT_RAW) - tp = (uint32*) op; - else { - assert(sp->tbuflen >= npixels); - tp = (uint32*) sp->tbuf; - } - _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0])); + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32*) op; + else { + if(sp->tbuflen < npixels) { + TIFFErrorExt(tif->tif_clientdata, module, + "Translation buffer too short"); + return (0); + } + tp = (uint32*) sp->tbuf; + } + _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0])); - bp = (unsigned char*) tif->tif_rawcp; - cc = tif->tif_rawcc; - /* get each byte string */ - for (shft = 4*8; (shft -= 8) >= 0; ) { - for (i = 0; i < npixels && cc > 0; ) - if (*bp >= 128) { /* run */ - rc = *bp++ + (2-128); - b = (uint32)*bp++ << shft; - cc -= 2; /* TODO: potential input buffer overrun when decoding corrupt or truncated data */ - while (rc-- && i < npixels) - tp[i++] |= b; - } else { /* non-run */ - rc = *bp++; /* nul is noop */ - while (--cc && rc-- && i < npixels) - tp[i++] |= (uint32)*bp++ << shft; - } - if (i != npixels) { + bp = (unsigned char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + /* get each byte string */ + for (shft = 4*8; (shft -= 8) >= 0; ) { + for (i = 0; i < npixels && cc > 0; ) { + if (*bp >= 128) { /* run */ + if( cc < 2 ) + break; + rc = *bp++ + (2-128); + b = (uint32)*bp++ << shft; + cc -= 2; + while (rc-- && i < npixels) + tp[i++] |= b; + } else { /* non-run */ + rc = *bp++; /* nul is noop */ + while (--cc && rc-- && i < npixels) + tp[i++] |= (uint32)*bp++ << shft; + } + } + if (i != npixels) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at row %lu (short %I64d pixels)", - (unsigned long) tif->tif_row, - (unsigned __int64) (npixels - i)); + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at row %lu (short %I64d pixels)", + (unsigned long) tif->tif_row, + (unsigned __int64) (npixels - i)); #else - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at row %lu (short %llu pixels)", - (unsigned long) tif->tif_row, - (unsigned long long) (npixels - i)); + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at row %lu (short %llu pixels)", + (unsigned long) tif->tif_row, + (unsigned long long) (npixels - i)); #endif - tif->tif_rawcp = (uint8*) bp; - tif->tif_rawcc = cc; - return (0); - } - } - (*sp->tfunc)(sp, op, npixels); - tif->tif_rawcp = (uint8*) bp; - tif->tif_rawcc = cc; - return (1); + tif->tif_rawcp = (uint8*) bp; + tif->tif_rawcc = cc; + return (0); + } + } + (*sp->tfunc)(sp, op, npixels); + tif->tif_rawcp = (uint8*) bp; + tif->tif_rawcc = cc; + return (1); } /* @@ -377,12 +396,17 @@ LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) static int LogLuvDecodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - tmsize_t rowlen = TIFFScanlineSize(tif); + tmsize_t rowlen = TIFFScanlineSize(tif); - assert(cc%rowlen == 0); - while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) - bp += rowlen, cc -= rowlen; - return (cc == 0); + if (rowlen == 0) + return 0; + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) { + bp += rowlen; + cc -= rowlen; + } + return (cc == 0); } /* @@ -393,12 +417,17 @@ LogLuvDecodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) static int LogLuvDecodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - tmsize_t rowlen = TIFFTileRowSize(tif); + tmsize_t rowlen = TIFFTileRowSize(tif); - assert(cc%rowlen == 0); - while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) - bp += rowlen, cc -= rowlen; - return (cc == 0); + if (rowlen == 0) + return 0; + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) { + bp += rowlen; + cc -= rowlen; + } + return (cc == 0); } /* @@ -407,91 +436,96 @@ LogLuvDecodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) static int LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - LogLuvState* sp = EncoderState(tif); - int shft; - tmsize_t i; - tmsize_t j; - tmsize_t npixels; - uint8* op; - int16* tp; - int16 b; - tmsize_t occ; - int rc=0, mask; - tmsize_t beg; + static const char module[] = "LogL16Encode"; + LogLuvState* sp = EncoderState(tif); + int shft; + tmsize_t i; + tmsize_t j; + tmsize_t npixels; + uint8* op; + int16* tp; + int16 b; + tmsize_t occ; + int rc=0, mask; + tmsize_t beg; - assert(s == 0); - assert(sp != NULL); - npixels = cc / sp->pixel_size; + assert(s == 0); + assert(sp != NULL); + npixels = cc / sp->pixel_size; - if (sp->user_datafmt == SGILOGDATAFMT_16BIT) - tp = (int16*) bp; - else { - tp = (int16*) sp->tbuf; - assert(sp->tbuflen >= npixels); - (*sp->tfunc)(sp, bp, npixels); - } - /* compress each byte string */ - op = tif->tif_rawcp; - occ = tif->tif_rawdatasize - tif->tif_rawcc; - for (shft = 2*8; (shft -= 8) >= 0; ) - for (i = 0; i < npixels; i += rc) { - if (occ < 4) { - tif->tif_rawcp = op; - tif->tif_rawcc = tif->tif_rawdatasize - occ; - if (!TIFFFlushData1(tif)) - return (-1); - op = tif->tif_rawcp; - occ = tif->tif_rawdatasize - tif->tif_rawcc; - } - mask = 0xff << shft; /* find next run */ - for (beg = i; beg < npixels; beg += rc) { - b = (int16) (tp[beg] & mask); - rc = 1; - while (rc < 127+2 && beg+rc < npixels && - (tp[beg+rc] & mask) == b) - rc++; - if (rc >= MINRUN) - break; /* long enough */ - } - if (beg-i > 1 && beg-i < MINRUN) { - b = (int16) (tp[i] & mask);/*check short run */ - j = i+1; - while ((tp[j++] & mask) == b) - if (j == beg) { - *op++ = (uint8)(128-2+j-i); - *op++ = (uint8)(b >> shft); - occ -= 2; - i = beg; - break; - } - } - while (i < beg) { /* write out non-run */ - if ((j = beg-i) > 127) j = 127; - if (occ < j+3) { - tif->tif_rawcp = op; - tif->tif_rawcc = tif->tif_rawdatasize - occ; - if (!TIFFFlushData1(tif)) - return (-1); - op = tif->tif_rawcp; - occ = tif->tif_rawdatasize - tif->tif_rawcc; - } - *op++ = (uint8) j; occ--; - while (j--) { - *op++ = (uint8) (tp[i++] >> shft & 0xff); - occ--; - } - } - if (rc >= MINRUN) { /* write out run */ - *op++ = (uint8) (128-2+rc); - *op++ = (uint8) (tp[beg] >> shft & 0xff); - occ -= 2; - } else - rc = 0; - } - tif->tif_rawcp = op; - tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (sp->user_datafmt == SGILOGDATAFMT_16BIT) + tp = (int16*) bp; + else { + tp = (int16*) sp->tbuf; + if(sp->tbuflen < npixels) { + TIFFErrorExt(tif->tif_clientdata, module, + "Translation buffer too short"); + return (0); + } + (*sp->tfunc)(sp, bp, npixels); + } + /* compress each byte string */ + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + for (shft = 2*8; (shft -= 8) >= 0; ) + for (i = 0; i < npixels; i += rc) { + if (occ < 4) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (0); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + mask = 0xff << shft; /* find next run */ + for (beg = i; beg < npixels; beg += rc) { + b = (int16) (tp[beg] & mask); + rc = 1; + while (rc < 127+2 && beg+rc < npixels && + (tp[beg+rc] & mask) == b) + rc++; + if (rc >= MINRUN) + break; /* long enough */ + } + if (beg-i > 1 && beg-i < MINRUN) { + b = (int16) (tp[i] & mask);/*check short run */ + j = i+1; + while ((tp[j++] & mask) == b) + if (j == beg) { + *op++ = (uint8)(128-2+j-i); + *op++ = (uint8)(b >> shft); + occ -= 2; + i = beg; + break; + } + } + while (i < beg) { /* write out non-run */ + if ((j = beg-i) > 127) j = 127; + if (occ < j+3) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (0); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + *op++ = (uint8) j; occ--; + while (j--) { + *op++ = (uint8) (tp[i++] >> shft & 0xff); + occ--; + } + } + if (rc >= MINRUN) { /* write out run */ + *op++ = (uint8) (128-2+rc); + *op++ = (uint8) (tp[beg] >> shft & 0xff); + occ -= 2; + } else + rc = 0; + } + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; - return (1); + return (1); } /* @@ -500,45 +534,50 @@ LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) static int LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - LogLuvState* sp = EncoderState(tif); - tmsize_t i; - tmsize_t npixels; - tmsize_t occ; - uint8* op; - uint32* tp; + static const char module[] = "LogLuvEncode24"; + LogLuvState* sp = EncoderState(tif); + tmsize_t i; + tmsize_t npixels; + tmsize_t occ; + uint8* op; + uint32* tp; - assert(s == 0); - assert(sp != NULL); - npixels = cc / sp->pixel_size; + assert(s == 0); + assert(sp != NULL); + npixels = cc / sp->pixel_size; - if (sp->user_datafmt == SGILOGDATAFMT_RAW) - tp = (uint32*) bp; - else { - tp = (uint32*) sp->tbuf; - assert(sp->tbuflen >= npixels); - (*sp->tfunc)(sp, bp, npixels); - } - /* write out encoded pixels */ - op = tif->tif_rawcp; - occ = tif->tif_rawdatasize - tif->tif_rawcc; - for (i = npixels; i--; ) { - if (occ < 3) { - tif->tif_rawcp = op; - tif->tif_rawcc = tif->tif_rawdatasize - occ; - if (!TIFFFlushData1(tif)) - return (-1); - op = tif->tif_rawcp; - occ = tif->tif_rawdatasize - tif->tif_rawcc; - } - *op++ = (uint8)(*tp >> 16); - *op++ = (uint8)(*tp >> 8 & 0xff); - *op++ = (uint8)(*tp++ & 0xff); - occ -= 3; - } - tif->tif_rawcp = op; - tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32*) bp; + else { + tp = (uint32*) sp->tbuf; + if(sp->tbuflen < npixels) { + TIFFErrorExt(tif->tif_clientdata, module, + "Translation buffer too short"); + return (0); + } + (*sp->tfunc)(sp, bp, npixels); + } + /* write out encoded pixels */ + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + for (i = npixels; i--; ) { + if (occ < 3) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (0); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + *op++ = (uint8)(*tp >> 16); + *op++ = (uint8)(*tp >> 8 & 0xff); + *op++ = (uint8)(*tp++ & 0xff); + occ -= 3; + } + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; - return (1); + return (1); } /* @@ -547,92 +586,97 @@ LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) static int LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - LogLuvState* sp = EncoderState(tif); - int shft; - tmsize_t i; - tmsize_t j; - tmsize_t npixels; - uint8* op; - uint32* tp; - uint32 b; - tmsize_t occ; - int rc=0, mask; - tmsize_t beg; + static const char module[] = "LogLuvEncode32"; + LogLuvState* sp = EncoderState(tif); + int shft; + tmsize_t i; + tmsize_t j; + tmsize_t npixels; + uint8* op; + uint32* tp; + uint32 b; + tmsize_t occ; + int rc=0, mask; + tmsize_t beg; - assert(s == 0); - assert(sp != NULL); + assert(s == 0); + assert(sp != NULL); - npixels = cc / sp->pixel_size; + npixels = cc / sp->pixel_size; - if (sp->user_datafmt == SGILOGDATAFMT_RAW) - tp = (uint32*) bp; - else { - tp = (uint32*) sp->tbuf; - assert(sp->tbuflen >= npixels); - (*sp->tfunc)(sp, bp, npixels); - } - /* compress each byte string */ - op = tif->tif_rawcp; - occ = tif->tif_rawdatasize - tif->tif_rawcc; - for (shft = 4*8; (shft -= 8) >= 0; ) - for (i = 0; i < npixels; i += rc) { - if (occ < 4) { - tif->tif_rawcp = op; - tif->tif_rawcc = tif->tif_rawdatasize - occ; - if (!TIFFFlushData1(tif)) - return (-1); - op = tif->tif_rawcp; - occ = tif->tif_rawdatasize - tif->tif_rawcc; - } - mask = 0xff << shft; /* find next run */ - for (beg = i; beg < npixels; beg += rc) { - b = tp[beg] & mask; - rc = 1; - while (rc < 127+2 && beg+rc < npixels && - (tp[beg+rc] & mask) == b) - rc++; - if (rc >= MINRUN) - break; /* long enough */ - } - if (beg-i > 1 && beg-i < MINRUN) { - b = tp[i] & mask; /* check short run */ - j = i+1; - while ((tp[j++] & mask) == b) - if (j == beg) { - *op++ = (uint8)(128-2+j-i); - *op++ = (uint8)(b >> shft); - occ -= 2; - i = beg; - break; - } - } - while (i < beg) { /* write out non-run */ - if ((j = beg-i) > 127) j = 127; - if (occ < j+3) { - tif->tif_rawcp = op; - tif->tif_rawcc = tif->tif_rawdatasize - occ; - if (!TIFFFlushData1(tif)) - return (-1); - op = tif->tif_rawcp; - occ = tif->tif_rawdatasize - tif->tif_rawcc; - } - *op++ = (uint8) j; occ--; - while (j--) { - *op++ = (uint8)(tp[i++] >> shft & 0xff); - occ--; - } - } - if (rc >= MINRUN) { /* write out run */ - *op++ = (uint8) (128-2+rc); - *op++ = (uint8)(tp[beg] >> shft & 0xff); - occ -= 2; - } else - rc = 0; - } - tif->tif_rawcp = op; - tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (sp->user_datafmt == SGILOGDATAFMT_RAW) + tp = (uint32*) bp; + else { + tp = (uint32*) sp->tbuf; + if(sp->tbuflen < npixels) { + TIFFErrorExt(tif->tif_clientdata, module, + "Translation buffer too short"); + return (0); + } + (*sp->tfunc)(sp, bp, npixels); + } + /* compress each byte string */ + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + for (shft = 4*8; (shft -= 8) >= 0; ) + for (i = 0; i < npixels; i += rc) { + if (occ < 4) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (0); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + mask = 0xff << shft; /* find next run */ + for (beg = i; beg < npixels; beg += rc) { + b = tp[beg] & mask; + rc = 1; + while (rc < 127+2 && beg+rc < npixels && + (tp[beg+rc] & mask) == b) + rc++; + if (rc >= MINRUN) + break; /* long enough */ + } + if (beg-i > 1 && beg-i < MINRUN) { + b = tp[i] & mask; /* check short run */ + j = i+1; + while ((tp[j++] & mask) == b) + if (j == beg) { + *op++ = (uint8)(128-2+j-i); + *op++ = (uint8)(b >> shft); + occ -= 2; + i = beg; + break; + } + } + while (i < beg) { /* write out non-run */ + if ((j = beg-i) > 127) j = 127; + if (occ < j+3) { + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; + if (!TIFFFlushData1(tif)) + return (0); + op = tif->tif_rawcp; + occ = tif->tif_rawdatasize - tif->tif_rawcc; + } + *op++ = (uint8) j; occ--; + while (j--) { + *op++ = (uint8)(tp[i++] >> shft & 0xff); + occ--; + } + } + if (rc >= MINRUN) { /* write out run */ + *op++ = (uint8) (128-2+rc); + *op++ = (uint8)(tp[beg] >> shft & 0xff); + occ -= 2; + } else + rc = 0; + } + tif->tif_rawcp = op; + tif->tif_rawcc = tif->tif_rawdatasize - occ; - return (1); + return (1); } /* @@ -642,12 +686,17 @@ LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) static int LogLuvEncodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - tmsize_t rowlen = TIFFScanlineSize(tif); + tmsize_t rowlen = TIFFScanlineSize(tif); - assert(cc%rowlen == 0); - while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) - bp += rowlen, cc -= rowlen; - return (cc == 0); + if (rowlen == 0) + return 0; + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) { + bp += rowlen; + cc -= rowlen; + } + return (cc == 0); } /* @@ -657,12 +706,17 @@ LogLuvEncodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) static int LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - tmsize_t rowlen = TIFFTileRowSize(tif); + tmsize_t rowlen = TIFFTileRowSize(tif); - assert(cc%rowlen == 0); - while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) - bp += rowlen, cc -= rowlen; - return (cc == 0); + if (rowlen == 0) + return 0; + + assert(cc%rowlen == 0); + while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) { + bp += rowlen; + cc -= rowlen; + } + return (cc == 0); } /* @@ -683,12 +737,14 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) #ifndef M_PI #define M_PI 3.14159265358979323846 #endif +#undef log2 /* Conflict with C'99 function */ #define log2(x) ((1./M_LN2)*log(x)) +#undef exp2 /* Conflict with C'99 function */ #define exp2(x) exp(M_LN2*(x)) #define itrunc(x,m) ((m)==SGILOGENCODE_NODITHER ? \ - (int)(x) : \ - (int)((x) + rand()*(1./RAND_MAX) - .5)) + (int)(x) : \ + (int)((x) + rand()*(1./RAND_MAX) - .5)) #if !LOGLUV_PUBLIC static @@ -696,13 +752,13 @@ static double LogL16toY(int p16) /* compute luminance from 16-bit LogL */ { - int Le = p16 & 0x7fff; - double Y; + int Le = p16 & 0x7fff; + double Y; - if (!Le) - return (0.); - Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.); - return (!(p16 & 0x8000) ? Y : -Y); + if (!Le) + return (0.); + Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.); + return (!(p16 & 0x8000) ? Y : -Y); } #if !LOGLUV_PUBLIC @@ -711,47 +767,47 @@ static int LogL16fromY(double Y, int em) /* get 16-bit LogL from Y */ { - if (Y >= 1.8371976e19) - return (0x7fff); - if (Y <= -1.8371976e19) - return (0xffff); - if (Y > 5.4136769e-20) - return itrunc(256.*(log2(Y) + 64.), em); - if (Y < -5.4136769e-20) - return (~0x7fff | itrunc(256.*(log2(-Y) + 64.), em)); - return (0); + if (Y >= 1.8371976e19) + return (0x7fff); + if (Y <= -1.8371976e19) + return (0xffff); + if (Y > 5.4136769e-20) + return itrunc(256.*(log2(Y) + 64.), em); + if (Y < -5.4136769e-20) + return (~0x7fff | itrunc(256.*(log2(-Y) + 64.), em)); + return (0); } static void L16toY(LogLuvState* sp, uint8* op, tmsize_t n) { - int16* l16 = (int16*) sp->tbuf; - float* yp = (float*) op; + int16* l16 = (int16*) sp->tbuf; + float* yp = (float*) op; - while (n-- > 0) - *yp++ = (float)LogL16toY(*l16++); + while (n-- > 0) + *yp++ = (float)LogL16toY(*l16++); } static void L16toGry(LogLuvState* sp, uint8* op, tmsize_t n) { - int16* l16 = (int16*) sp->tbuf; - uint8* gp = (uint8*) op; + int16* l16 = (int16*) sp->tbuf; + uint8* gp = (uint8*) op; - while (n-- > 0) { - double Y = LogL16toY(*l16++); - *gp++ = (uint8) ((Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y))); - } + while (n-- > 0) { + double Y = LogL16toY(*l16++); + *gp++ = (uint8) ((Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y))); + } } static void L16fromY(LogLuvState* sp, uint8* op, tmsize_t n) { - int16* l16 = (int16*) sp->tbuf; - float* yp = (float*) op; + int16* l16 = (int16*) sp->tbuf; + float* yp = (float*) op; - while (n-- > 0) - *l16++ = (int16) (LogL16fromY(*yp++, sp->encode_meth)); + while (n-- > 0) + *l16++ = (int16) (LogL16fromY(*yp++, sp->encode_meth)); } #if !LOGLUV_PUBLIC @@ -760,16 +816,16 @@ static void XYZtoRGB24(float xyz[3], uint8 rgb[3]) { - double r, g, b; - /* assume CCIR-709 primaries */ - r = 2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2]; - g = -1.022*xyz[0] + 1.978*xyz[1] + 0.044*xyz[2]; - b = 0.061*xyz[0] + -0.224*xyz[1] + 1.163*xyz[2]; - /* assume 2.0 gamma for speed */ - /* could use integer sqrt approx., but this is probably faster */ - rgb[0] = (uint8)((r<=0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r))); - rgb[1] = (uint8)((g<=0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g))); - rgb[2] = (uint8)((b<=0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b))); + double r, g, b; + /* assume CCIR-709 primaries */ + r = 2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2]; + g = -1.022*xyz[0] + 1.978*xyz[1] + 0.044*xyz[2]; + b = 0.061*xyz[0] + -0.224*xyz[1] + 1.163*xyz[2]; + /* assume 2.0 gamma for speed */ + /* could use integer sqrt approx., but this is probably faster */ + rgb[0] = (uint8)((r<=0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r))); + rgb[1] = (uint8)((g<=0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g))); + rgb[2] = (uint8)((b<=0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b))); } #if !LOGLUV_PUBLIC @@ -778,9 +834,9 @@ static double LogL10toY(int p10) /* compute luminance from 10-bit LogL */ { - if (p10 == 0) - return (0.); - return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.)); + if (p10 == 0) + return (0.); + return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.)); } #if !LOGLUV_PUBLIC @@ -789,66 +845,66 @@ static int LogL10fromY(double Y, int em) /* get 10-bit LogL from Y */ { - if (Y >= 15.742) - return (0x3ff); - else if (Y <= .00024283) - return (0); - else - return itrunc(64.*(log2(Y) + 12.), em); + if (Y >= 15.742) + return (0x3ff); + else if (Y <= .00024283) + return (0); + else + return itrunc(64.*(log2(Y) + 12.), em); } #define NANGLES 100 #define uv2ang(u, v) ( (NANGLES*.499999999/M_PI) \ - * atan2((v)-V_NEU,(u)-U_NEU) + .5*NANGLES ) + * atan2((v)-V_NEU,(u)-U_NEU) + .5*NANGLES ) static int oog_encode(double u, double v) /* encode out-of-gamut chroma */ { - static int oog_table[NANGLES]; - static int initialized = 0; - register int i; + static int oog_table[NANGLES]; + static int initialized = 0; + register int i; - if (!initialized) { /* set up perimeter table */ - double eps[NANGLES], ua, va, ang, epsa; - int ui, vi, ustep; - for (i = NANGLES; i--; ) - eps[i] = 2.; - for (vi = UV_NVS; vi--; ) { - va = UV_VSTART + (vi+.5)*UV_SQSIZ; - ustep = uv_row[vi].nus-1; - if (vi == UV_NVS-1 || vi == 0 || ustep <= 0) - ustep = 1; - for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) { - ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ; - ang = uv2ang(ua, va); - i = (int) ang; - epsa = fabs(ang - (i+.5)); - if (epsa < eps[i]) { - oog_table[i] = uv_row[vi].ncum + ui; - eps[i] = epsa; - } - } - } - for (i = NANGLES; i--; ) /* fill any holes */ - if (eps[i] > 1.5) { - int i1, i2; - for (i1 = 1; i1 < NANGLES/2; i1++) - if (eps[(i+i1)%NANGLES] < 1.5) - break; - for (i2 = 1; i2 < NANGLES/2; i2++) - if (eps[(i+NANGLES-i2)%NANGLES] < 1.5) - break; - if (i1 < i2) - oog_table[i] = - oog_table[(i+i1)%NANGLES]; - else - oog_table[i] = - oog_table[(i+NANGLES-i2)%NANGLES]; - } - initialized = 1; - } - i = (int) uv2ang(u, v); /* look up hue angle */ - return (oog_table[i]); + if (!initialized) { /* set up perimeter table */ + double eps[NANGLES], ua, va, ang, epsa; + int ui, vi, ustep; + for (i = NANGLES; i--; ) + eps[i] = 2.; + for (vi = UV_NVS; vi--; ) { + va = UV_VSTART + (vi+.5)*UV_SQSIZ; + ustep = uv_row[vi].nus-1; + if (vi == UV_NVS-1 || vi == 0 || ustep <= 0) + ustep = 1; + for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) { + ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ; + ang = uv2ang(ua, va); + i = (int) ang; + epsa = fabs(ang - (i+.5)); + if (epsa < eps[i]) { + oog_table[i] = uv_row[vi].ncum + ui; + eps[i] = epsa; + } + } + } + for (i = NANGLES; i--; ) /* fill any holes */ + if (eps[i] > 1.5) { + int i1, i2; + for (i1 = 1; i1 < NANGLES/2; i1++) + if (eps[(i+i1)%NANGLES] < 1.5) + break; + for (i2 = 1; i2 < NANGLES/2; i2++) + if (eps[(i+NANGLES-i2)%NANGLES] < 1.5) + break; + if (i1 < i2) + oog_table[i] = + oog_table[(i+i1)%NANGLES]; + else + oog_table[i] = + oog_table[(i+NANGLES-i2)%NANGLES]; + } + initialized = 1; + } + i = (int) uv2ang(u, v); /* look up hue angle */ + return (oog_table[i]); } #undef uv2ang @@ -860,20 +916,20 @@ static int uv_encode(double u, double v, int em) /* encode (u',v') coordinates */ { - register int vi, ui; + register int vi, ui; - if (v < UV_VSTART) - return oog_encode(u, v); - vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em); - if (vi >= UV_NVS) - return oog_encode(u, v); - if (u < uv_row[vi].ustart) - return oog_encode(u, v); - ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em); - if (ui >= uv_row[vi].nus) - return oog_encode(u, v); + if (v < UV_VSTART) + return oog_encode(u, v); + vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em); + if (vi >= UV_NVS) + return oog_encode(u, v); + if (u < uv_row[vi].ustart) + return oog_encode(u, v); + ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em); + if (ui >= uv_row[vi].nus) + return oog_encode(u, v); - return (uv_row[vi].ncum + ui); + return (uv_row[vi].ncum + ui); } #if !LOGLUV_PUBLIC @@ -882,30 +938,30 @@ static int uv_decode(double *up, double *vp, int c) /* decode (u',v') index */ { - int upper, lower; - register int ui, vi; + int upper, lower; + register int ui, vi; - if (c < 0 || c >= UV_NDIVS) - return (-1); - lower = 0; /* binary search */ - upper = UV_NVS; - while (upper - lower > 1) { - vi = (lower + upper) >> 1; - ui = c - uv_row[vi].ncum; - if (ui > 0) - lower = vi; - else if (ui < 0) - upper = vi; - else { - lower = vi; - break; - } - } - vi = lower; - ui = c - uv_row[vi].ncum; - *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ; - *vp = UV_VSTART + (vi+.5)*UV_SQSIZ; - return (0); + if (c < 0 || c >= UV_NDIVS) + return (-1); + lower = 0; /* binary search */ + upper = UV_NVS; + while (upper - lower > 1) { + vi = (lower + upper) >> 1; + ui = c - uv_row[vi].ncum; + if (ui > 0) + lower = vi; + else if (ui < 0) + upper = vi; + else { + lower = vi; + break; + } + } + vi = lower; + ui = c - uv_row[vi].ncum; + *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ; + *vp = UV_VSTART + (vi+.5)*UV_SQSIZ; + return (0); } #if !LOGLUV_PUBLIC @@ -914,26 +970,26 @@ static void LogLuv24toXYZ(uint32 p, float XYZ[3]) { - int Ce; - double L, u, v, s, x, y; - /* decode luminance */ - L = LogL10toY(p>>14 & 0x3ff); - if (L <= 0.) { - XYZ[0] = XYZ[1] = XYZ[2] = 0.; - return; - } - /* decode color */ - Ce = p & 0x3fff; - if (uv_decode(&u, &v, Ce) < 0) { - u = U_NEU; v = V_NEU; - } - s = 1./(6.*u - 16.*v + 12.); - x = 9.*u * s; - y = 4.*v * s; - /* convert to XYZ */ - XYZ[0] = (float)(x/y * L); - XYZ[1] = (float)L; - XYZ[2] = (float)((1.-x-y)/y * L); + int Ce; + double L, u, v, s, x, y; + /* decode luminance */ + L = LogL10toY(p>>14 & 0x3ff); + if (L <= 0.) { + XYZ[0] = XYZ[1] = XYZ[2] = 0.; + return; + } + /* decode color */ + Ce = p & 0x3fff; + if (uv_decode(&u, &v, Ce) < 0) { + u = U_NEU; v = V_NEU; + } + s = 1./(6.*u - 16.*v + 12.); + x = 9.*u * s; + y = 4.*v * s; + /* convert to XYZ */ + XYZ[0] = (float)(x/y * L); + XYZ[1] = (float)L; + XYZ[2] = (float)((1.-x-y)/y * L); } #if !LOGLUV_PUBLIC @@ -942,111 +998,111 @@ static uint32 LogLuv24fromXYZ(float XYZ[3], int em) { - int Le, Ce; - double u, v, s; - /* encode luminance */ - Le = LogL10fromY(XYZ[1], em); - /* encode color */ - s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; - if (!Le || s <= 0.) { - u = U_NEU; - v = V_NEU; - } else { - u = 4.*XYZ[0] / s; - v = 9.*XYZ[1] / s; - } - Ce = uv_encode(u, v, em); - if (Ce < 0) /* never happens */ - Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); - /* combine encodings */ - return (Le << 14 | Ce); + int Le, Ce; + double u, v, s; + /* encode luminance */ + Le = LogL10fromY(XYZ[1], em); + /* encode color */ + s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; + if (!Le || s <= 0.) { + u = U_NEU; + v = V_NEU; + } else { + u = 4.*XYZ[0] / s; + v = 9.*XYZ[1] / s; + } + Ce = uv_encode(u, v, em); + if (Ce < 0) /* never happens */ + Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); + /* combine encodings */ + return (Le << 14 | Ce); } static void Luv24toXYZ(LogLuvState* sp, uint8* op, tmsize_t n) { - uint32* luv = (uint32*) sp->tbuf; - float* xyz = (float*) op; + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; - while (n-- > 0) { - LogLuv24toXYZ(*luv, xyz); - xyz += 3; - luv++; - } + while (n-- > 0) { + LogLuv24toXYZ(*luv, xyz); + xyz += 3; + luv++; + } } static void Luv24toLuv48(LogLuvState* sp, uint8* op, tmsize_t n) { - uint32* luv = (uint32*) sp->tbuf; - int16* luv3 = (int16*) op; + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; - while (n-- > 0) { - double u, v; + while (n-- > 0) { + double u, v; - *luv3++ = (int16)((*luv >> 12 & 0xffd) + 13314); - if (uv_decode(&u, &v, *luv&0x3fff) < 0) { - u = U_NEU; - v = V_NEU; - } - *luv3++ = (int16)(u * (1L<<15)); - *luv3++ = (int16)(v * (1L<<15)); - luv++; - } + *luv3++ = (int16)((*luv >> 12 & 0xffd) + 13314); + if (uv_decode(&u, &v, *luv&0x3fff) < 0) { + u = U_NEU; + v = V_NEU; + } + *luv3++ = (int16)(u * (1L<<15)); + *luv3++ = (int16)(v * (1L<<15)); + luv++; + } } static void Luv24toRGB(LogLuvState* sp, uint8* op, tmsize_t n) { - uint32* luv = (uint32*) sp->tbuf; - uint8* rgb = (uint8*) op; + uint32* luv = (uint32*) sp->tbuf; + uint8* rgb = (uint8*) op; - while (n-- > 0) { - float xyz[3]; + while (n-- > 0) { + float xyz[3]; - LogLuv24toXYZ(*luv++, xyz); - XYZtoRGB24(xyz, rgb); - rgb += 3; - } + LogLuv24toXYZ(*luv++, xyz); + XYZtoRGB24(xyz, rgb); + rgb += 3; + } } static void Luv24fromXYZ(LogLuvState* sp, uint8* op, tmsize_t n) { - uint32* luv = (uint32*) sp->tbuf; - float* xyz = (float*) op; + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; - while (n-- > 0) { - *luv++ = LogLuv24fromXYZ(xyz, sp->encode_meth); - xyz += 3; - } + while (n-- > 0) { + *luv++ = LogLuv24fromXYZ(xyz, sp->encode_meth); + xyz += 3; + } } static void Luv24fromLuv48(LogLuvState* sp, uint8* op, tmsize_t n) { - uint32* luv = (uint32*) sp->tbuf; - int16* luv3 = (int16*) op; + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; - while (n-- > 0) { - int Le, Ce; + while (n-- > 0) { + int Le, Ce; - if (luv3[0] <= 0) - Le = 0; - else if (luv3[0] >= (1<<12)+3314) - Le = (1<<10) - 1; - else if (sp->encode_meth == SGILOGENCODE_NODITHER) - Le = (luv3[0]-3314) >> 2; - else - Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth); + if (luv3[0] <= 0) + Le = 0; + else if (luv3[0] >= (1<<12)+3314) + Le = (1<<10) - 1; + else if (sp->encode_meth == SGILOGENCODE_NODITHER) + Le = (luv3[0]-3314) >> 2; + else + Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth); - Ce = uv_encode((luv3[1]+.5)/(1<<15), (luv3[2]+.5)/(1<<15), - sp->encode_meth); - if (Ce < 0) /* never happens */ - Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); - *luv++ = (uint32)Le << 14 | Ce; - luv3 += 3; - } + Ce = uv_encode((luv3[1]+.5)/(1<<15), (luv3[2]+.5)/(1<<15), + sp->encode_meth); + if (Ce < 0) /* never happens */ + Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); + *luv++ = (uint32)Le << 14 | Ce; + luv3 += 3; + } } #if !LOGLUV_PUBLIC @@ -1055,23 +1111,23 @@ static void LogLuv32toXYZ(uint32 p, float XYZ[3]) { - double L, u, v, s, x, y; - /* decode luminance */ - L = LogL16toY((int)p >> 16); - if (L <= 0.) { - XYZ[0] = XYZ[1] = XYZ[2] = 0.; - return; - } - /* decode color */ - u = 1./UVSCALE * ((p>>8 & 0xff) + .5); - v = 1./UVSCALE * ((p & 0xff) + .5); - s = 1./(6.*u - 16.*v + 12.); - x = 9.*u * s; - y = 4.*v * s; - /* convert to XYZ */ - XYZ[0] = (float)(x/y * L); - XYZ[1] = (float)L; - XYZ[2] = (float)((1.-x-y)/y * L); + double L, u, v, s, x, y; + /* decode luminance */ + L = LogL16toY((int)p >> 16); + if (L <= 0.) { + XYZ[0] = XYZ[1] = XYZ[2] = 0.; + return; + } + /* decode color */ + u = 1./UVSCALE * ((p>>8 & 0xff) + .5); + v = 1./UVSCALE * ((p & 0xff) + .5); + s = 1./(6.*u - 16.*v + 12.); + x = 9.*u * s; + y = 4.*v * s; + /* convert to XYZ */ + XYZ[0] = (float)(x/y * L); + XYZ[1] = (float)L; + XYZ[2] = (float)((1.-x-y)/y * L); } #if !LOGLUV_PUBLIC @@ -1080,530 +1136,556 @@ static uint32 LogLuv32fromXYZ(float XYZ[3], int em) { - unsigned int Le, ue, ve; - double u, v, s; - /* encode luminance */ - Le = (unsigned int)LogL16fromY(XYZ[1], em); - /* encode color */ - s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; - if (!Le || s <= 0.) { - u = U_NEU; - v = V_NEU; - } else { - u = 4.*XYZ[0] / s; - v = 9.*XYZ[1] / s; - } - if (u <= 0.) ue = 0; - else ue = itrunc(UVSCALE*u, em); - if (ue > 255) ue = 255; - if (v <= 0.) ve = 0; - else ve = itrunc(UVSCALE*v, em); - if (ve > 255) ve = 255; - /* combine encodings */ - return (Le << 16 | ue << 8 | ve); + unsigned int Le, ue, ve; + double u, v, s; + /* encode luminance */ + Le = (unsigned int)LogL16fromY(XYZ[1], em); + /* encode color */ + s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; + if (!Le || s <= 0.) { + u = U_NEU; + v = V_NEU; + } else { + u = 4.*XYZ[0] / s; + v = 9.*XYZ[1] / s; + } + if (u <= 0.) ue = 0; + else ue = itrunc(UVSCALE*u, em); + if (ue > 255) ue = 255; + if (v <= 0.) ve = 0; + else ve = itrunc(UVSCALE*v, em); + if (ve > 255) ve = 255; + /* combine encodings */ + return (Le << 16 | ue << 8 | ve); } static void Luv32toXYZ(LogLuvState* sp, uint8* op, tmsize_t n) { - uint32* luv = (uint32*) sp->tbuf; - float* xyz = (float*) op; + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; - while (n-- > 0) { - LogLuv32toXYZ(*luv++, xyz); - xyz += 3; - } + while (n-- > 0) { + LogLuv32toXYZ(*luv++, xyz); + xyz += 3; + } } static void Luv32toLuv48(LogLuvState* sp, uint8* op, tmsize_t n) { - uint32* luv = (uint32*) sp->tbuf; - int16* luv3 = (int16*) op; + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; - while (n-- > 0) { - double u, v; + while (n-- > 0) { + double u, v; - *luv3++ = (int16)(*luv >> 16); - u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5); - v = 1./UVSCALE * ((*luv & 0xff) + .5); - *luv3++ = (int16)(u * (1L<<15)); - *luv3++ = (int16)(v * (1L<<15)); - luv++; - } + *luv3++ = (int16)(*luv >> 16); + u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5); + v = 1./UVSCALE * ((*luv & 0xff) + .5); + *luv3++ = (int16)(u * (1L<<15)); + *luv3++ = (int16)(v * (1L<<15)); + luv++; + } } static void Luv32toRGB(LogLuvState* sp, uint8* op, tmsize_t n) { - uint32* luv = (uint32*) sp->tbuf; - uint8* rgb = (uint8*) op; + uint32* luv = (uint32*) sp->tbuf; + uint8* rgb = (uint8*) op; - while (n-- > 0) { - float xyz[3]; + while (n-- > 0) { + float xyz[3]; - LogLuv32toXYZ(*luv++, xyz); - XYZtoRGB24(xyz, rgb); - rgb += 3; - } + LogLuv32toXYZ(*luv++, xyz); + XYZtoRGB24(xyz, rgb); + rgb += 3; + } } static void Luv32fromXYZ(LogLuvState* sp, uint8* op, tmsize_t n) { - uint32* luv = (uint32*) sp->tbuf; - float* xyz = (float*) op; + uint32* luv = (uint32*) sp->tbuf; + float* xyz = (float*) op; - while (n-- > 0) { - *luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth); - xyz += 3; - } + while (n-- > 0) { + *luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth); + xyz += 3; + } } static void Luv32fromLuv48(LogLuvState* sp, uint8* op, tmsize_t n) { - uint32* luv = (uint32*) sp->tbuf; - int16* luv3 = (int16*) op; + uint32* luv = (uint32*) sp->tbuf; + int16* luv3 = (int16*) op; - if (sp->encode_meth == SGILOGENCODE_NODITHER) { - while (n-- > 0) { - *luv++ = (uint32)luv3[0] << 16 | - (luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) | - (luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff); - luv3 += 3; - } - return; - } - while (n-- > 0) { - *luv++ = (uint32)luv3[0] << 16 | - (itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) | - (itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff); - luv3 += 3; - } + if (sp->encode_meth == SGILOGENCODE_NODITHER) { + while (n-- > 0) { + *luv++ = (uint32)luv3[0] << 16 | + (luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) | + (luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff); + luv3 += 3; + } + return; + } + while (n-- > 0) { + *luv++ = (uint32)luv3[0] << 16 | + (itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) | + (itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff); + luv3 += 3; + } } static void _logLuvNop(LogLuvState* sp, uint8* op, tmsize_t n) { - (void) sp; (void) op; (void) n; + (void) sp; (void) op; (void) n; } static int LogL16GuessDataFmt(TIFFDirectory *td) { #define PACK(s,b,f) (((b)<<6)|((s)<<3)|(f)) - switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) { - case PACK(1, 32, SAMPLEFORMAT_IEEEFP): - return (SGILOGDATAFMT_FLOAT); - case PACK(1, 16, SAMPLEFORMAT_VOID): - case PACK(1, 16, SAMPLEFORMAT_INT): - case PACK(1, 16, SAMPLEFORMAT_UINT): - return (SGILOGDATAFMT_16BIT); - case PACK(1, 8, SAMPLEFORMAT_VOID): - case PACK(1, 8, SAMPLEFORMAT_UINT): - return (SGILOGDATAFMT_8BIT); - } + switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) { + case PACK(1, 32, SAMPLEFORMAT_IEEEFP): + return (SGILOGDATAFMT_FLOAT); + case PACK(1, 16, SAMPLEFORMAT_VOID): + case PACK(1, 16, SAMPLEFORMAT_INT): + case PACK(1, 16, SAMPLEFORMAT_UINT): + return (SGILOGDATAFMT_16BIT); + case PACK(1, 8, SAMPLEFORMAT_VOID): + case PACK(1, 8, SAMPLEFORMAT_UINT): + return (SGILOGDATAFMT_8BIT); + } #undef PACK - return (SGILOGDATAFMT_UNKNOWN); + return (SGILOGDATAFMT_UNKNOWN); } + +#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0)) +#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1) + static tmsize_t multiply_ms(tmsize_t m1, tmsize_t m2) { - tmsize_t bytes = m1 * m2; - - if (m1 && bytes / m1 != m2) - bytes = 0; - - return bytes; + if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 ) + return 0; + return m1 * m2; } static int LogL16InitState(TIFF* tif) { - static const char module[] = "LogL16InitState"; - TIFFDirectory *td = &tif->tif_dir; - LogLuvState* sp = DecoderState(tif); + static const char module[] = "LogL16InitState"; + TIFFDirectory *td = &tif->tif_dir; + LogLuvState* sp = DecoderState(tif); - assert(sp != NULL); - assert(td->td_photometric == PHOTOMETRIC_LOGL); + assert(sp != NULL); + assert(td->td_photometric == PHOTOMETRIC_LOGL); - /* for some reason, we can't do this in TIFFInitLogL16 */ - if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN) - sp->user_datafmt = LogL16GuessDataFmt(td); - switch (sp->user_datafmt) { - case SGILOGDATAFMT_FLOAT: - sp->pixel_size = sizeof (float); - break; - case SGILOGDATAFMT_16BIT: - sp->pixel_size = sizeof (int16); - break; - case SGILOGDATAFMT_8BIT: - sp->pixel_size = sizeof (uint8); - break; - default: - TIFFErrorExt(tif->tif_clientdata, module, - "No support for converting user data format to LogL"); - return (0); - } + if( td->td_samplesperpixel != 1 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Sorry, can not handle LogL image with %s=%d", + "Samples/pixel", td->td_samplesperpixel); + return 0; + } + + /* for some reason, we can't do this in TIFFInitLogL16 */ + if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN) + sp->user_datafmt = LogL16GuessDataFmt(td); + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->pixel_size = sizeof (float); + break; + case SGILOGDATAFMT_16BIT: + sp->pixel_size = sizeof (int16); + break; + case SGILOGDATAFMT_8BIT: + sp->pixel_size = sizeof (uint8); + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, + "No support for converting user data format to LogL"); + return (0); + } if( isTiled(tif) ) sp->tbuflen = multiply_ms(td->td_tilewidth, td->td_tilelength); - else + else if( td->td_rowsperstrip < td->td_imagelength ) sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_rowsperstrip); - if (multiply_ms(sp->tbuflen, sizeof (int16)) == 0 || - (sp->tbuf = (uint8*) _TIFFmalloc(sp->tbuflen * sizeof (int16))) == NULL) { - TIFFErrorExt(tif->tif_clientdata, module, "No space for SGILog translation buffer"); - return (0); - } - return (1); + else + sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_imagelength); + if (multiply_ms(sp->tbuflen, sizeof (int16)) == 0 || + (sp->tbuf = (uint8*) _TIFFmalloc(sp->tbuflen * sizeof (int16))) == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, "No space for SGILog translation buffer"); + return (0); + } + return (1); } static int LogLuvGuessDataFmt(TIFFDirectory *td) { - int guess; + int guess; - /* - * If the user didn't tell us their datafmt, - * take our best guess from the bitspersample. - */ + /* + * If the user didn't tell us their datafmt, + * take our best guess from the bitspersample. + */ #define PACK(a,b) (((a)<<3)|(b)) - switch (PACK(td->td_bitspersample, td->td_sampleformat)) { - case PACK(32, SAMPLEFORMAT_IEEEFP): - guess = SGILOGDATAFMT_FLOAT; - break; - case PACK(32, SAMPLEFORMAT_VOID): - case PACK(32, SAMPLEFORMAT_UINT): - case PACK(32, SAMPLEFORMAT_INT): - guess = SGILOGDATAFMT_RAW; - break; - case PACK(16, SAMPLEFORMAT_VOID): - case PACK(16, SAMPLEFORMAT_INT): - case PACK(16, SAMPLEFORMAT_UINT): - guess = SGILOGDATAFMT_16BIT; - break; - case PACK( 8, SAMPLEFORMAT_VOID): - case PACK( 8, SAMPLEFORMAT_UINT): - guess = SGILOGDATAFMT_8BIT; - break; - default: - guess = SGILOGDATAFMT_UNKNOWN; - break; + switch (PACK(td->td_bitspersample, td->td_sampleformat)) { + case PACK(32, SAMPLEFORMAT_IEEEFP): + guess = SGILOGDATAFMT_FLOAT; + break; + case PACK(32, SAMPLEFORMAT_VOID): + case PACK(32, SAMPLEFORMAT_UINT): + case PACK(32, SAMPLEFORMAT_INT): + guess = SGILOGDATAFMT_RAW; + break; + case PACK(16, SAMPLEFORMAT_VOID): + case PACK(16, SAMPLEFORMAT_INT): + case PACK(16, SAMPLEFORMAT_UINT): + guess = SGILOGDATAFMT_16BIT; + break; + case PACK( 8, SAMPLEFORMAT_VOID): + case PACK( 8, SAMPLEFORMAT_UINT): + guess = SGILOGDATAFMT_8BIT; + break; + default: + guess = SGILOGDATAFMT_UNKNOWN; + break; #undef PACK - } - /* - * Double-check samples per pixel. - */ - switch (td->td_samplesperpixel) { - case 1: - if (guess != SGILOGDATAFMT_RAW) - guess = SGILOGDATAFMT_UNKNOWN; - break; - case 3: - if (guess == SGILOGDATAFMT_RAW) - guess = SGILOGDATAFMT_UNKNOWN; - break; - default: - guess = SGILOGDATAFMT_UNKNOWN; - break; - } - return (guess); + } + /* + * Double-check samples per pixel. + */ + switch (td->td_samplesperpixel) { + case 1: + if (guess != SGILOGDATAFMT_RAW) + guess = SGILOGDATAFMT_UNKNOWN; + break; + case 3: + if (guess == SGILOGDATAFMT_RAW) + guess = SGILOGDATAFMT_UNKNOWN; + break; + default: + guess = SGILOGDATAFMT_UNKNOWN; + break; + } + return (guess); } static int LogLuvInitState(TIFF* tif) { - static const char module[] = "LogLuvInitState"; - TIFFDirectory* td = &tif->tif_dir; - LogLuvState* sp = DecoderState(tif); + static const char module[] = "LogLuvInitState"; + TIFFDirectory* td = &tif->tif_dir; + LogLuvState* sp = DecoderState(tif); - assert(sp != NULL); - assert(td->td_photometric == PHOTOMETRIC_LOGLUV); + assert(sp != NULL); + assert(td->td_photometric == PHOTOMETRIC_LOGLUV); - /* for some reason, we can't do this in TIFFInitLogLuv */ - if (td->td_planarconfig != PLANARCONFIG_CONTIG) { - TIFFErrorExt(tif->tif_clientdata, module, - "SGILog compression cannot handle non-contiguous data"); - return (0); - } - if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN) - sp->user_datafmt = LogLuvGuessDataFmt(td); - switch (sp->user_datafmt) { - case SGILOGDATAFMT_FLOAT: - sp->pixel_size = 3*sizeof (float); - break; - case SGILOGDATAFMT_16BIT: - sp->pixel_size = 3*sizeof (int16); - break; - case SGILOGDATAFMT_RAW: - sp->pixel_size = sizeof (uint32); - break; - case SGILOGDATAFMT_8BIT: - sp->pixel_size = 3*sizeof (uint8); - break; - default: - TIFFErrorExt(tif->tif_clientdata, module, - "No support for converting user data format to LogLuv"); - return (0); - } + /* for some reason, we can't do this in TIFFInitLogLuv */ + if (td->td_planarconfig != PLANARCONFIG_CONTIG) { + TIFFErrorExt(tif->tif_clientdata, module, + "SGILog compression cannot handle non-contiguous data"); + return (0); + } + if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN) + sp->user_datafmt = LogLuvGuessDataFmt(td); + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->pixel_size = 3*sizeof (float); + break; + case SGILOGDATAFMT_16BIT: + sp->pixel_size = 3*sizeof (int16); + break; + case SGILOGDATAFMT_RAW: + sp->pixel_size = sizeof (uint32); + break; + case SGILOGDATAFMT_8BIT: + sp->pixel_size = 3*sizeof (uint8); + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, + "No support for converting user data format to LogLuv"); + return (0); + } if( isTiled(tif) ) sp->tbuflen = multiply_ms(td->td_tilewidth, td->td_tilelength); - else + else if( td->td_rowsperstrip < td->td_imagelength ) sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_rowsperstrip); - if (multiply_ms(sp->tbuflen, sizeof (uint32)) == 0 || - (sp->tbuf = (uint8*) _TIFFmalloc(sp->tbuflen * sizeof (uint32))) == NULL) { - TIFFErrorExt(tif->tif_clientdata, module, "No space for SGILog translation buffer"); - return (0); - } - return (1); + else + sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_imagelength); + if (multiply_ms(sp->tbuflen, sizeof (uint32)) == 0 || + (sp->tbuf = (uint8*) _TIFFmalloc(sp->tbuflen * sizeof (uint32))) == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, "No space for SGILog translation buffer"); + return (0); + } + return (1); } static int LogLuvFixupTags(TIFF* tif) { - (void) tif; - return (1); + (void) tif; + return (1); } static int LogLuvSetupDecode(TIFF* tif) { - static const char module[] = "LogLuvSetupDecode"; - LogLuvState* sp = DecoderState(tif); - TIFFDirectory* td = &tif->tif_dir; + static const char module[] = "LogLuvSetupDecode"; + LogLuvState* sp = DecoderState(tif); + TIFFDirectory* td = &tif->tif_dir; - tif->tif_postdecode = _TIFFNoPostDecode; - switch (td->td_photometric) { - case PHOTOMETRIC_LOGLUV: - if (!LogLuvInitState(tif)) - break; - if (td->td_compression == COMPRESSION_SGILOG24) { - tif->tif_decoderow = LogLuvDecode24; - switch (sp->user_datafmt) { - case SGILOGDATAFMT_FLOAT: - sp->tfunc = Luv24toXYZ; - break; - case SGILOGDATAFMT_16BIT: - sp->tfunc = Luv24toLuv48; - break; - case SGILOGDATAFMT_8BIT: - sp->tfunc = Luv24toRGB; - break; - } - } else { - tif->tif_decoderow = LogLuvDecode32; - switch (sp->user_datafmt) { - case SGILOGDATAFMT_FLOAT: - sp->tfunc = Luv32toXYZ; - break; - case SGILOGDATAFMT_16BIT: - sp->tfunc = Luv32toLuv48; - break; - case SGILOGDATAFMT_8BIT: - sp->tfunc = Luv32toRGB; - break; - } - } - return (1); - case PHOTOMETRIC_LOGL: - if (!LogL16InitState(tif)) - break; - tif->tif_decoderow = LogL16Decode; - switch (sp->user_datafmt) { - case SGILOGDATAFMT_FLOAT: - sp->tfunc = L16toY; - break; - case SGILOGDATAFMT_8BIT: - sp->tfunc = L16toGry; - break; - } - return (1); - default: - TIFFErrorExt(tif->tif_clientdata, module, - "Inappropriate photometric interpretation %d for SGILog compression; %s", - td->td_photometric, "must be either LogLUV or LogL"); - break; - } - return (0); + tif->tif_postdecode = _TIFFNoPostDecode; + switch (td->td_photometric) { + case PHOTOMETRIC_LOGLUV: + if (!LogLuvInitState(tif)) + break; + if (td->td_compression == COMPRESSION_SGILOG24) { + tif->tif_decoderow = LogLuvDecode24; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv24toXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv24toLuv48; + break; + case SGILOGDATAFMT_8BIT: + sp->tfunc = Luv24toRGB; + break; + } + } else { + tif->tif_decoderow = LogLuvDecode32; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv32toXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv32toLuv48; + break; + case SGILOGDATAFMT_8BIT: + sp->tfunc = Luv32toRGB; + break; + } + } + return (1); + case PHOTOMETRIC_LOGL: + if (!LogL16InitState(tif)) + break; + tif->tif_decoderow = LogL16Decode; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = L16toY; + break; + case SGILOGDATAFMT_8BIT: + sp->tfunc = L16toGry; + break; + } + return (1); + default: + TIFFErrorExt(tif->tif_clientdata, module, + "Inappropriate photometric interpretation %d for SGILog compression; %s", + td->td_photometric, "must be either LogLUV or LogL"); + break; + } + return (0); } static int LogLuvSetupEncode(TIFF* tif) { - static const char module[] = "LogLuvSetupEncode"; - LogLuvState* sp = EncoderState(tif); - TIFFDirectory* td = &tif->tif_dir; + static const char module[] = "LogLuvSetupEncode"; + LogLuvState* sp = EncoderState(tif); + TIFFDirectory* td = &tif->tif_dir; - switch (td->td_photometric) { - case PHOTOMETRIC_LOGLUV: - if (!LogLuvInitState(tif)) - break; - if (td->td_compression == COMPRESSION_SGILOG24) { - tif->tif_encoderow = LogLuvEncode24; - switch (sp->user_datafmt) { - case SGILOGDATAFMT_FLOAT: - sp->tfunc = Luv24fromXYZ; - break; - case SGILOGDATAFMT_16BIT: - sp->tfunc = Luv24fromLuv48; - break; - case SGILOGDATAFMT_RAW: - break; - default: - goto notsupported; - } - } else { - tif->tif_encoderow = LogLuvEncode32; - switch (sp->user_datafmt) { - case SGILOGDATAFMT_FLOAT: - sp->tfunc = Luv32fromXYZ; - break; - case SGILOGDATAFMT_16BIT: - sp->tfunc = Luv32fromLuv48; - break; - case SGILOGDATAFMT_RAW: - break; - default: - goto notsupported; - } - } - break; - case PHOTOMETRIC_LOGL: - if (!LogL16InitState(tif)) - break; - tif->tif_encoderow = LogL16Encode; - switch (sp->user_datafmt) { - case SGILOGDATAFMT_FLOAT: - sp->tfunc = L16fromY; - break; - case SGILOGDATAFMT_16BIT: - break; - default: - goto notsupported; - } - break; - default: - TIFFErrorExt(tif->tif_clientdata, module, - "Inappropriate photometric interpretation %d for SGILog compression; %s", - td->td_photometric, "must be either LogLUV or LogL"); - break; - } - return (1); + switch (td->td_photometric) { + case PHOTOMETRIC_LOGLUV: + if (!LogLuvInitState(tif)) + break; + if (td->td_compression == COMPRESSION_SGILOG24) { + tif->tif_encoderow = LogLuvEncode24; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv24fromXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv24fromLuv48; + break; + case SGILOGDATAFMT_RAW: + break; + default: + goto notsupported; + } + } else { + tif->tif_encoderow = LogLuvEncode32; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = Luv32fromXYZ; + break; + case SGILOGDATAFMT_16BIT: + sp->tfunc = Luv32fromLuv48; + break; + case SGILOGDATAFMT_RAW: + break; + default: + goto notsupported; + } + } + break; + case PHOTOMETRIC_LOGL: + if (!LogL16InitState(tif)) + break; + tif->tif_encoderow = LogL16Encode; + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + sp->tfunc = L16fromY; + break; + case SGILOGDATAFMT_16BIT: + break; + default: + goto notsupported; + } + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, + "Inappropriate photometric interpretation %d for SGILog compression; %s", + td->td_photometric, "must be either LogLUV or LogL"); + break; + } + sp->encoder_state = 1; + return (1); notsupported: - TIFFErrorExt(tif->tif_clientdata, module, - "SGILog compression supported only for %s, or raw data", - td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv"); - return (0); + TIFFErrorExt(tif->tif_clientdata, module, + "SGILog compression supported only for %s, or raw data", + td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv"); + return (0); } static void LogLuvClose(TIFF* tif) { - TIFFDirectory *td = &tif->tif_dir; + LogLuvState* sp = (LogLuvState*) tif->tif_data; + TIFFDirectory *td = &tif->tif_dir; - /* - * For consistency, we always want to write out the same - * bitspersample and sampleformat for our TIFF file, - * regardless of the data format being used by the application. - * Since this routine is called after tags have been set but - * before they have been recorded in the file, we reset them here. - */ - td->td_samplesperpixel = - (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3; - td->td_bitspersample = 16; - td->td_sampleformat = SAMPLEFORMAT_INT; + assert(sp != 0); + /* + * For consistency, we always want to write out the same + * bitspersample and sampleformat for our TIFF file, + * regardless of the data format being used by the application. + * Since this routine is called after tags have been set but + * before they have been recorded in the file, we reset them here. + * Note: this is really a nasty approach. See PixarLogClose + */ + if( sp->encoder_state ) + { + /* See PixarLogClose. Might avoid issues with tags whose size depends + * on those below, but not completely sure this is enough. */ + td->td_samplesperpixel = + (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3; + td->td_bitspersample = 16; + td->td_sampleformat = SAMPLEFORMAT_INT; + } } static void LogLuvCleanup(TIFF* tif) { - LogLuvState* sp = (LogLuvState *)tif->tif_data; + LogLuvState* sp = (LogLuvState *)tif->tif_data; - assert(sp != 0); + assert(sp != 0); - tif->tif_tagmethods.vgetfield = sp->vgetparent; - tif->tif_tagmethods.vsetfield = sp->vsetparent; + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; - if (sp->tbuf) - _TIFFfree(sp->tbuf); - _TIFFfree(sp); - tif->tif_data = NULL; + if (sp->tbuf) + _TIFFfree(sp->tbuf); + _TIFFfree(sp); + tif->tif_data = NULL; - _TIFFSetDefaultCompressionState(tif); + _TIFFSetDefaultCompressionState(tif); } static int LogLuvVSetField(TIFF* tif, uint32 tag, va_list ap) { - static const char module[] = "LogLuvVSetField"; - LogLuvState* sp = DecoderState(tif); - int bps, fmt; + static const char module[] = "LogLuvVSetField"; + LogLuvState* sp = DecoderState(tif); + int bps, fmt; - switch (tag) { - case TIFFTAG_SGILOGDATAFMT: - sp->user_datafmt = (int) va_arg(ap, int); - /* - * Tweak the TIFF header so that the rest of libtiff knows what - * size of data will be passed between app and library, and - * assume that the app knows what it is doing and is not - * confused by these header manipulations... - */ - switch (sp->user_datafmt) { - case SGILOGDATAFMT_FLOAT: - bps = 32, fmt = SAMPLEFORMAT_IEEEFP; - break; - case SGILOGDATAFMT_16BIT: - bps = 16, fmt = SAMPLEFORMAT_INT; - break; - case SGILOGDATAFMT_RAW: - bps = 32, fmt = SAMPLEFORMAT_UINT; - TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); - break; - case SGILOGDATAFMT_8BIT: - bps = 8, fmt = SAMPLEFORMAT_UINT; - break; - default: - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "Unknown data format %d for LogLuv compression", - sp->user_datafmt); - return (0); - } - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); - TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt); - /* - * Must recalculate sizes should bits/sample change. - */ - tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t) -1; - tif->tif_scanlinesize = TIFFScanlineSize(tif); - return (1); - case TIFFTAG_SGILOGENCODE: - sp->encode_meth = (int) va_arg(ap, int); - if (sp->encode_meth != SGILOGENCODE_NODITHER && - sp->encode_meth != SGILOGENCODE_RANDITHER) { - TIFFErrorExt(tif->tif_clientdata, module, - "Unknown encoding %d for LogLuv compression", - sp->encode_meth); - return (0); - } - return (1); - default: - return (*sp->vsetparent)(tif, tag, ap); - } + switch (tag) { + case TIFFTAG_SGILOGDATAFMT: + sp->user_datafmt = (int) va_arg(ap, int); + /* + * Tweak the TIFF header so that the rest of libtiff knows what + * size of data will be passed between app and library, and + * assume that the app knows what it is doing and is not + * confused by these header manipulations... + */ + switch (sp->user_datafmt) { + case SGILOGDATAFMT_FLOAT: + bps = 32; + fmt = SAMPLEFORMAT_IEEEFP; + break; + case SGILOGDATAFMT_16BIT: + bps = 16; + fmt = SAMPLEFORMAT_INT; + break; + case SGILOGDATAFMT_RAW: + bps = 32; + fmt = SAMPLEFORMAT_UINT; + TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); + break; + case SGILOGDATAFMT_8BIT: + bps = 8; + fmt = SAMPLEFORMAT_UINT; + break; + default: + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Unknown data format %d for LogLuv compression", + sp->user_datafmt); + return (0); + } + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt); + /* + * Must recalculate sizes should bits/sample change. + */ + tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t) -1; + tif->tif_scanlinesize = TIFFScanlineSize(tif); + return (1); + case TIFFTAG_SGILOGENCODE: + sp->encode_meth = (int) va_arg(ap, int); + if (sp->encode_meth != SGILOGENCODE_NODITHER && + sp->encode_meth != SGILOGENCODE_RANDITHER) { + TIFFErrorExt(tif->tif_clientdata, module, + "Unknown encoding %d for LogLuv compression", + sp->encode_meth); + return (0); + } + return (1); + default: + return (*sp->vsetparent)(tif, tag, ap); + } } static int LogLuvVGetField(TIFF* tif, uint32 tag, va_list ap) { - LogLuvState *sp = (LogLuvState *)tif->tif_data; + LogLuvState *sp = (LogLuvState *)tif->tif_data; - switch (tag) { - case TIFFTAG_SGILOGDATAFMT: - *va_arg(ap, int*) = sp->user_datafmt; - return (1); - default: - return (*sp->vgetparent)(tif, tag, ap); - } + switch (tag) { + case TIFFTAG_SGILOGDATAFMT: + *va_arg(ap, int*) = sp->user_datafmt; + return (1); + default: + return (*sp->vgetparent)(tif, tag, ap); + } } static const TIFFField LogLuvFields[] = { @@ -1614,62 +1696,62 @@ static const TIFFField LogLuvFields[] = { int TIFFInitSGILog(TIFF* tif, int scheme) { - static const char module[] = "TIFFInitSGILog"; - LogLuvState* sp; + static const char module[] = "TIFFInitSGILog"; + LogLuvState* sp; - assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG); + assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG); - /* - * Merge codec-specific tag information. - */ - if (!_TIFFMergeFields(tif, LogLuvFields, - TIFFArrayCount(LogLuvFields))) { - TIFFErrorExt(tif->tif_clientdata, module, - "Merging SGILog codec-specific tags failed"); - return 0; - } + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, LogLuvFields, + TIFFArrayCount(LogLuvFields))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Merging SGILog codec-specific tags failed"); + return 0; + } - /* - * Allocate state block so tag methods have storage to record values. - */ - tif->tif_data = (uint8*) _TIFFmalloc(sizeof (LogLuvState)); - if (tif->tif_data == NULL) - goto bad; - sp = (LogLuvState*) tif->tif_data; - _TIFFmemset((void*)sp, 0, sizeof (*sp)); - sp->user_datafmt = SGILOGDATAFMT_UNKNOWN; - sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ? - SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER; - sp->tfunc = _logLuvNop; + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (uint8*) _TIFFmalloc(sizeof (LogLuvState)); + if (tif->tif_data == NULL) + goto bad; + sp = (LogLuvState*) tif->tif_data; + _TIFFmemset((void*)sp, 0, sizeof (*sp)); + sp->user_datafmt = SGILOGDATAFMT_UNKNOWN; + sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ? + SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER; + sp->tfunc = _logLuvNop; - /* - * Install codec methods. - * NB: tif_decoderow & tif_encoderow are filled - * in at setup time. - */ - tif->tif_fixuptags = LogLuvFixupTags; - tif->tif_setupdecode = LogLuvSetupDecode; - tif->tif_decodestrip = LogLuvDecodeStrip; - tif->tif_decodetile = LogLuvDecodeTile; - tif->tif_setupencode = LogLuvSetupEncode; - tif->tif_encodestrip = LogLuvEncodeStrip; - tif->tif_encodetile = LogLuvEncodeTile; - tif->tif_close = LogLuvClose; - tif->tif_cleanup = LogLuvCleanup; + /* + * Install codec methods. + * NB: tif_decoderow & tif_encoderow are filled + * in at setup time. + */ + tif->tif_fixuptags = LogLuvFixupTags; + tif->tif_setupdecode = LogLuvSetupDecode; + tif->tif_decodestrip = LogLuvDecodeStrip; + tif->tif_decodetile = LogLuvDecodeTile; + tif->tif_setupencode = LogLuvSetupEncode; + tif->tif_encodestrip = LogLuvEncodeStrip; + tif->tif_encodetile = LogLuvEncodeTile; + tif->tif_close = LogLuvClose; + tif->tif_cleanup = LogLuvCleanup; - /* - * Override parent get/set field methods. - */ - sp->vgetparent = tif->tif_tagmethods.vgetfield; - tif->tif_tagmethods.vgetfield = LogLuvVGetField; /* hook for codec tags */ - sp->vsetparent = tif->tif_tagmethods.vsetfield; - tif->tif_tagmethods.vsetfield = LogLuvVSetField; /* hook for codec tags */ + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = LogLuvVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = LogLuvVSetField; /* hook for codec tags */ - return (1); + return (1); bad: - TIFFErrorExt(tif->tif_clientdata, module, - "%s: No space for LogLuv state block", tif->tif_name); - return (0); + TIFFErrorExt(tif->tif_clientdata, module, + "%s: No space for LogLuv state block", tif->tif_name); + return (0); } #endif /* LOGLUV_SUPPORT */ diff --git a/3rdparty/libtiff/tif_lzma.c b/3rdparty/libtiff/tif_lzma.c index 7f40484896..80fc394245 100644 --- a/3rdparty/libtiff/tif_lzma.c +++ b/3rdparty/libtiff/tif_lzma.c @@ -1,4 +1,4 @@ -/* $Id: tif_lzma.c,v 1.4 2011-12-22 00:29:29 bfriesen Exp $ */ +/* $Id: tif_lzma.c,v 1.6 2016-09-17 09:18:59 erouault Exp $ */ /* * Copyright (c) 2010, Andrey Kiselev @@ -44,19 +44,19 @@ * State block for each open TIFF file using LZMA2 compression/decompression. */ typedef struct { - TIFFPredictorState predict; + TIFFPredictorState predict; lzma_stream stream; - lzma_filter filters[LZMA_FILTERS_MAX + 1]; - lzma_options_delta opt_delta; /* delta filter options */ - lzma_options_lzma opt_lzma; /* LZMA2 filter options */ - int preset; /* compression level */ - lzma_check check; /* type of the integrity check */ - int state; /* state flags */ + lzma_filter filters[LZMA_FILTERS_MAX + 1]; + lzma_options_delta opt_delta; /* delta filter options */ + lzma_options_lzma opt_lzma; /* LZMA2 filter options */ + int preset; /* compression level */ + lzma_check check; /* type of the integrity check */ + int state; /* state flags */ #define LSTATE_INIT_DECODE 0x01 #define LSTATE_INIT_ENCODE 0x02 - TIFFVGetMethod vgetparent; /* super-class method */ - TIFFVSetMethod vsetparent; /* super-class method */ + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ } LZMAState; #define LState(tif) ((LZMAState*) (tif)->tif_data) @@ -69,58 +69,58 @@ static int LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s); static const char * LZMAStrerror(lzma_ret ret) { - switch (ret) { - case LZMA_OK: - return "operation completed successfully"; - case LZMA_STREAM_END: - return "end of stream was reached"; - case LZMA_NO_CHECK: - return "input stream has no integrity check"; - case LZMA_UNSUPPORTED_CHECK: - return "cannot calculate the integrity check"; - case LZMA_GET_CHECK: - return "integrity check type is now available"; - case LZMA_MEM_ERROR: - return "cannot allocate memory"; - case LZMA_MEMLIMIT_ERROR: - return "memory usage limit was reached"; - case LZMA_FORMAT_ERROR: - return "file format not recognized"; - case LZMA_OPTIONS_ERROR: - return "invalid or unsupported options"; - case LZMA_DATA_ERROR: - return "data is corrupt"; - case LZMA_BUF_ERROR: - return "no progress is possible (stream is truncated or corrupt)"; - case LZMA_PROG_ERROR: - return "programming error"; - default: - return "unindentified liblzma error"; - } + switch (ret) { + case LZMA_OK: + return "operation completed successfully"; + case LZMA_STREAM_END: + return "end of stream was reached"; + case LZMA_NO_CHECK: + return "input stream has no integrity check"; + case LZMA_UNSUPPORTED_CHECK: + return "cannot calculate the integrity check"; + case LZMA_GET_CHECK: + return "integrity check type is now available"; + case LZMA_MEM_ERROR: + return "cannot allocate memory"; + case LZMA_MEMLIMIT_ERROR: + return "memory usage limit was reached"; + case LZMA_FORMAT_ERROR: + return "file format not recognized"; + case LZMA_OPTIONS_ERROR: + return "invalid or unsupported options"; + case LZMA_DATA_ERROR: + return "data is corrupt"; + case LZMA_BUF_ERROR: + return "no progress is possible (stream is truncated or corrupt)"; + case LZMA_PROG_ERROR: + return "programming error"; + default: + return "unidentified liblzma error"; + } } static int LZMAFixupTags(TIFF* tif) { - (void) tif; - return 1; + (void) tif; + return 1; } static int LZMASetupDecode(TIFF* tif) { - LZMAState* sp = DecoderState(tif); - - assert(sp != NULL); + LZMAState* sp = DecoderState(tif); + assert(sp != NULL); + /* if we were last encoding, terminate this mode */ - if (sp->state & LSTATE_INIT_ENCODE) { - lzma_end(&sp->stream); - sp->state = 0; - } + if (sp->state & LSTATE_INIT_ENCODE) { + lzma_end(&sp->stream); + sp->state = 0; + } - sp->state |= LSTATE_INIT_DECODE; - return 1; + sp->state |= LSTATE_INIT_DECODE; + return 1; } /* @@ -129,116 +129,116 @@ LZMASetupDecode(TIFF* tif) static int LZMAPreDecode(TIFF* tif, uint16 s) { - static const char module[] = "LZMAPreDecode"; - LZMAState* sp = DecoderState(tif); - lzma_ret ret; + static const char module[] = "LZMAPreDecode"; + LZMAState* sp = DecoderState(tif); + lzma_ret ret; - (void) s; - assert(sp != NULL); + (void) s; + assert(sp != NULL); - if( (sp->state & LSTATE_INIT_DECODE) == 0 ) + if( (sp->state & LSTATE_INIT_DECODE) == 0 ) tif->tif_setupdecode(tif); - sp->stream.next_in = tif->tif_rawdata; - sp->stream.avail_in = (size_t) tif->tif_rawcc; - if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) { - TIFFErrorExt(tif->tif_clientdata, module, - "Liblzma cannot deal with buffers this size"); - return 0; - } + sp->stream.next_in = tif->tif_rawdata; + sp->stream.avail_in = (size_t) tif->tif_rawcc; + if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) { + TIFFErrorExt(tif->tif_clientdata, module, + "Liblzma cannot deal with buffers this size"); + return 0; + } - /* - * Disable memory limit when decoding. UINT64_MAX is a flag to disable - * the limit, we are passing (uint64_t)-1 which should be the same. - */ - ret = lzma_stream_decoder(&sp->stream, (uint64_t)-1, 0); - if (ret != LZMA_OK) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error initializing the stream decoder, %s", - LZMAStrerror(ret)); - return 0; - } - return 1; + /* + * Disable memory limit when decoding. UINT64_MAX is a flag to disable + * the limit, we are passing (uint64_t)-1 which should be the same. + */ + ret = lzma_stream_decoder(&sp->stream, (uint64_t)-1, 0); + if (ret != LZMA_OK) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error initializing the stream decoder, %s", + LZMAStrerror(ret)); + return 0; + } + return 1; } static int LZMADecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) { - static const char module[] = "LZMADecode"; - LZMAState* sp = DecoderState(tif); + static const char module[] = "LZMADecode"; + LZMAState* sp = DecoderState(tif); - (void) s; - assert(sp != NULL); - assert(sp->state == LSTATE_INIT_DECODE); + (void) s; + assert(sp != NULL); + assert(sp->state == LSTATE_INIT_DECODE); sp->stream.next_in = tif->tif_rawcp; sp->stream.avail_in = (size_t) tif->tif_rawcc; - sp->stream.next_out = op; - sp->stream.avail_out = (size_t) occ; - if ((tmsize_t)sp->stream.avail_out != occ) { - TIFFErrorExt(tif->tif_clientdata, module, - "Liblzma cannot deal with buffers this size"); - return 0; - } + sp->stream.next_out = op; + sp->stream.avail_out = (size_t) occ; + if ((tmsize_t)sp->stream.avail_out != occ) { + TIFFErrorExt(tif->tif_clientdata, module, + "Liblzma cannot deal with buffers this size"); + return 0; + } - do { - /* - * Save the current stream state to properly recover from the - * decoding errors later. - */ - const uint8_t *next_in = sp->stream.next_in; - size_t avail_in = sp->stream.avail_in; + do { + /* + * Save the current stream state to properly recover from the + * decoding errors later. + */ + const uint8_t *next_in = sp->stream.next_in; + size_t avail_in = sp->stream.avail_in; - lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN); - if (ret == LZMA_STREAM_END) - break; - if (ret == LZMA_MEMLIMIT_ERROR) { - lzma_ret r = lzma_stream_decoder(&sp->stream, - lzma_memusage(&sp->stream), 0); - if (r != LZMA_OK) { - TIFFErrorExt(tif->tif_clientdata, module, - "Error initializing the stream decoder, %s", - LZMAStrerror(r)); - break; - } - sp->stream.next_in = next_in; - sp->stream.avail_in = avail_in; - continue; - } - if (ret != LZMA_OK) { - TIFFErrorExt(tif->tif_clientdata, module, - "Decoding error at scanline %lu, %s", - (unsigned long) tif->tif_row, LZMAStrerror(ret)); - break; - } - } while (sp->stream.avail_out > 0); - if (sp->stream.avail_out != 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at scanline %lu (short %lu bytes)", - (unsigned long) tif->tif_row, (unsigned long) sp->stream.avail_out); - return 0; - } + lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN); + if (ret == LZMA_STREAM_END) + break; + if (ret == LZMA_MEMLIMIT_ERROR) { + lzma_ret r = lzma_stream_decoder(&sp->stream, + lzma_memusage(&sp->stream), 0); + if (r != LZMA_OK) { + TIFFErrorExt(tif->tif_clientdata, module, + "Error initializing the stream decoder, %s", + LZMAStrerror(r)); + break; + } + sp->stream.next_in = next_in; + sp->stream.avail_in = avail_in; + continue; + } + if (ret != LZMA_OK) { + TIFFErrorExt(tif->tif_clientdata, module, + "Decoding error at scanline %lu, %s", + (unsigned long) tif->tif_row, LZMAStrerror(ret)); + break; + } + } while (sp->stream.avail_out > 0); + if (sp->stream.avail_out != 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at scanline %lu (short %lu bytes)", + (unsigned long) tif->tif_row, (unsigned long) sp->stream.avail_out); + return 0; + } tif->tif_rawcp = (uint8 *)sp->stream.next_in; /* cast away const */ tif->tif_rawcc = sp->stream.avail_in; - - return 1; + + return 1; } static int LZMASetupEncode(TIFF* tif) { - LZMAState* sp = EncoderState(tif); + LZMAState* sp = EncoderState(tif); - assert(sp != NULL); - if (sp->state & LSTATE_INIT_DECODE) { - lzma_end(&sp->stream); - sp->state = 0; - } + assert(sp != NULL); + if (sp->state & LSTATE_INIT_DECODE) { + lzma_end(&sp->stream); + sp->state = 0; + } - sp->state |= LSTATE_INIT_ENCODE; - return 1; + sp->state |= LSTATE_INIT_ENCODE; + return 1; } /* @@ -247,22 +247,22 @@ LZMASetupEncode(TIFF* tif) static int LZMAPreEncode(TIFF* tif, uint16 s) { - static const char module[] = "LZMAPreEncode"; - LZMAState *sp = EncoderState(tif); + static const char module[] = "LZMAPreEncode"; + LZMAState *sp = EncoderState(tif); - (void) s; - assert(sp != NULL); - if( sp->state != LSTATE_INIT_ENCODE ) + (void) s; + assert(sp != NULL); + if( sp->state != LSTATE_INIT_ENCODE ) tif->tif_setupencode(tif); - sp->stream.next_out = tif->tif_rawdata; - sp->stream.avail_out = (size_t)tif->tif_rawdatasize; - if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) { - TIFFErrorExt(tif->tif_clientdata, module, - "Liblzma cannot deal with buffers this size"); - return 0; - } - return (lzma_stream_encoder(&sp->stream, sp->filters, sp->check) == LZMA_OK); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = (size_t)tif->tif_rawdatasize; + if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) { + TIFFErrorExt(tif->tif_clientdata, module, + "Liblzma cannot deal with buffers this size"); + return 0; + } + return (lzma_stream_encoder(&sp->stream, sp->filters, sp->check) == LZMA_OK); } /* @@ -271,36 +271,36 @@ LZMAPreEncode(TIFF* tif, uint16 s) static int LZMAEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - static const char module[] = "LZMAEncode"; - LZMAState *sp = EncoderState(tif); + static const char module[] = "LZMAEncode"; + LZMAState *sp = EncoderState(tif); - assert(sp != NULL); - assert(sp->state == LSTATE_INIT_ENCODE); + assert(sp != NULL); + assert(sp->state == LSTATE_INIT_ENCODE); - (void) s; - sp->stream.next_in = bp; - sp->stream.avail_in = (size_t) cc; - if ((tmsize_t)sp->stream.avail_in != cc) { - TIFFErrorExt(tif->tif_clientdata, module, - "Liblzma cannot deal with buffers this size"); - return 0; - } - do { - lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN); - if (ret != LZMA_OK) { - TIFFErrorExt(tif->tif_clientdata, module, - "Encoding error at scanline %lu, %s", - (unsigned long) tif->tif_row, LZMAStrerror(ret)); - return 0; - } - if (sp->stream.avail_out == 0) { - tif->tif_rawcc = tif->tif_rawdatasize; - TIFFFlushData1(tif); - sp->stream.next_out = tif->tif_rawdata; - sp->stream.avail_out = (size_t)tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in LZMAPreEncode */ - } - } while (sp->stream.avail_in > 0); - return 1; + (void) s; + sp->stream.next_in = bp; + sp->stream.avail_in = (size_t) cc; + if ((tmsize_t)sp->stream.avail_in != cc) { + TIFFErrorExt(tif->tif_clientdata, module, + "Liblzma cannot deal with buffers this size"); + return 0; + } + do { + lzma_ret ret = lzma_code(&sp->stream, LZMA_RUN); + if (ret != LZMA_OK) { + TIFFErrorExt(tif->tif_clientdata, module, + "Encoding error at scanline %lu, %s", + (unsigned long) tif->tif_row, LZMAStrerror(ret)); + return 0; + } + if (sp->stream.avail_out == 0) { + tif->tif_rawcc = tif->tif_rawdatasize; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = (size_t)tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in LZMAPreEncode */ + } + } while (sp->stream.avail_in > 0); + return 1; } /* @@ -310,186 +310,186 @@ LZMAEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) static int LZMAPostEncode(TIFF* tif) { - static const char module[] = "LZMAPostEncode"; - LZMAState *sp = EncoderState(tif); - lzma_ret ret; + static const char module[] = "LZMAPostEncode"; + LZMAState *sp = EncoderState(tif); + lzma_ret ret; - sp->stream.avail_in = 0; - do { - ret = lzma_code(&sp->stream, LZMA_FINISH); - switch (ret) { - case LZMA_STREAM_END: - case LZMA_OK: - if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) { - tif->tif_rawcc = - tif->tif_rawdatasize - sp->stream.avail_out; - TIFFFlushData1(tif); - sp->stream.next_out = tif->tif_rawdata; - sp->stream.avail_out = (size_t)tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in ZIPPreEncode */ - } - break; - default: - TIFFErrorExt(tif->tif_clientdata, module, "Liblzma error: %s", - LZMAStrerror(ret)); - return 0; - } - } while (ret != LZMA_STREAM_END); - return 1; + sp->stream.avail_in = 0; + do { + ret = lzma_code(&sp->stream, LZMA_FINISH); + switch (ret) { + case LZMA_STREAM_END: + case LZMA_OK: + if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) { + tif->tif_rawcc = + tif->tif_rawdatasize - sp->stream.avail_out; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = (size_t)tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in ZIPPreEncode */ + } + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, "Liblzma error: %s", + LZMAStrerror(ret)); + return 0; + } + } while (ret != LZMA_STREAM_END); + return 1; } static void LZMACleanup(TIFF* tif) { - LZMAState* sp = LState(tif); + LZMAState* sp = LState(tif); - assert(sp != 0); + assert(sp != 0); - (void)TIFFPredictorCleanup(tif); + (void)TIFFPredictorCleanup(tif); - tif->tif_tagmethods.vgetfield = sp->vgetparent; - tif->tif_tagmethods.vsetfield = sp->vsetparent; + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; - if (sp->state) { - lzma_end(&sp->stream); - sp->state = 0; - } - _TIFFfree(sp); - tif->tif_data = NULL; + if (sp->state) { + lzma_end(&sp->stream); + sp->state = 0; + } + _TIFFfree(sp); + tif->tif_data = NULL; - _TIFFSetDefaultCompressionState(tif); + _TIFFSetDefaultCompressionState(tif); } static int LZMAVSetField(TIFF* tif, uint32 tag, va_list ap) { - static const char module[] = "LZMAVSetField"; - LZMAState* sp = LState(tif); + static const char module[] = "LZMAVSetField"; + LZMAState* sp = LState(tif); - switch (tag) { - case TIFFTAG_LZMAPRESET: - sp->preset = (int) va_arg(ap, int); - lzma_lzma_preset(&sp->opt_lzma, sp->preset); - if (sp->state & LSTATE_INIT_ENCODE) { - lzma_ret ret = lzma_stream_encoder(&sp->stream, - sp->filters, - sp->check); - if (ret != LZMA_OK) { - TIFFErrorExt(tif->tif_clientdata, module, - "Liblzma error: %s", - LZMAStrerror(ret)); - } - } - return 1; - default: - return (*sp->vsetparent)(tif, tag, ap); - } - /*NOTREACHED*/ + switch (tag) { + case TIFFTAG_LZMAPRESET: + sp->preset = (int) va_arg(ap, int); + lzma_lzma_preset(&sp->opt_lzma, sp->preset); + if (sp->state & LSTATE_INIT_ENCODE) { + lzma_ret ret = lzma_stream_encoder(&sp->stream, + sp->filters, + sp->check); + if (ret != LZMA_OK) { + TIFFErrorExt(tif->tif_clientdata, module, + "Liblzma error: %s", + LZMAStrerror(ret)); + } + } + return 1; + default: + return (*sp->vsetparent)(tif, tag, ap); + } + /*NOTREACHED*/ } static int LZMAVGetField(TIFF* tif, uint32 tag, va_list ap) { - LZMAState* sp = LState(tif); + LZMAState* sp = LState(tif); - switch (tag) { - case TIFFTAG_LZMAPRESET: - *va_arg(ap, int*) = sp->preset; - break; - default: - return (*sp->vgetparent)(tif, tag, ap); - } - return 1; + switch (tag) { + case TIFFTAG_LZMAPRESET: + *va_arg(ap, int*) = sp->preset; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return 1; } static const TIFFField lzmaFields[] = { - { TIFFTAG_LZMAPRESET, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, - FIELD_PSEUDO, TRUE, FALSE, "LZMA2 Compression Preset", NULL }, + { TIFFTAG_LZMAPRESET, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, + FIELD_PSEUDO, TRUE, FALSE, "LZMA2 Compression Preset", NULL }, }; int TIFFInitLZMA(TIFF* tif, int scheme) { - static const char module[] = "TIFFInitLZMA"; - LZMAState* sp; - lzma_stream tmp_stream = LZMA_STREAM_INIT; + static const char module[] = "TIFFInitLZMA"; + LZMAState* sp; + lzma_stream tmp_stream = LZMA_STREAM_INIT; - assert( scheme == COMPRESSION_LZMA ); + assert( scheme == COMPRESSION_LZMA ); - /* - * Merge codec-specific tag information. - */ - if (!_TIFFMergeFields(tif, lzmaFields, TIFFArrayCount(lzmaFields))) { - TIFFErrorExt(tif->tif_clientdata, module, - "Merging LZMA2 codec-specific tags failed"); - return 0; - } + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, lzmaFields, TIFFArrayCount(lzmaFields))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Merging LZMA2 codec-specific tags failed"); + return 0; + } - /* - * Allocate state block so tag methods have storage to record values. - */ - tif->tif_data = (uint8*) _TIFFmalloc(sizeof(LZMAState)); - if (tif->tif_data == NULL) - goto bad; - sp = LState(tif); - memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream)); + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (uint8*) _TIFFmalloc(sizeof(LZMAState)); + if (tif->tif_data == NULL) + goto bad; + sp = LState(tif); + memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream)); - /* - * Override parent get/set field methods. - */ - sp->vgetparent = tif->tif_tagmethods.vgetfield; - tif->tif_tagmethods.vgetfield = LZMAVGetField; /* hook for codec tags */ - sp->vsetparent = tif->tif_tagmethods.vsetfield; - tif->tif_tagmethods.vsetfield = LZMAVSetField; /* hook for codec tags */ + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = LZMAVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = LZMAVSetField; /* hook for codec tags */ - /* Default values for codec-specific fields */ - sp->preset = LZMA_PRESET_DEFAULT; /* default comp. level */ - sp->check = LZMA_CHECK_NONE; - sp->state = 0; + /* Default values for codec-specific fields */ + sp->preset = LZMA_PRESET_DEFAULT; /* default comp. level */ + sp->check = LZMA_CHECK_NONE; + sp->state = 0; - /* Data filters. So far we are using delta and LZMA2 filters only. */ - sp->opt_delta.type = LZMA_DELTA_TYPE_BYTE; - /* - * The sample size in bytes seems to be reasonable distance for delta - * filter. - */ - sp->opt_delta.dist = (tif->tif_dir.td_bitspersample % 8) ? - 1 : tif->tif_dir.td_bitspersample / 8; - sp->filters[0].id = LZMA_FILTER_DELTA; - sp->filters[0].options = &sp->opt_delta; + /* Data filters. So far we are using delta and LZMA2 filters only. */ + sp->opt_delta.type = LZMA_DELTA_TYPE_BYTE; + /* + * The sample size in bytes seems to be reasonable distance for delta + * filter. + */ + sp->opt_delta.dist = (tif->tif_dir.td_bitspersample % 8) ? + 1 : tif->tif_dir.td_bitspersample / 8; + sp->filters[0].id = LZMA_FILTER_DELTA; + sp->filters[0].options = &sp->opt_delta; - lzma_lzma_preset(&sp->opt_lzma, sp->preset); - sp->filters[1].id = LZMA_FILTER_LZMA2; - sp->filters[1].options = &sp->opt_lzma; + lzma_lzma_preset(&sp->opt_lzma, sp->preset); + sp->filters[1].id = LZMA_FILTER_LZMA2; + sp->filters[1].options = &sp->opt_lzma; - sp->filters[2].id = LZMA_VLI_UNKNOWN; - sp->filters[2].options = NULL; + sp->filters[2].id = LZMA_VLI_UNKNOWN; + sp->filters[2].options = NULL; - /* - * Install codec methods. - */ - tif->tif_fixuptags = LZMAFixupTags; - tif->tif_setupdecode = LZMASetupDecode; - tif->tif_predecode = LZMAPreDecode; - tif->tif_decoderow = LZMADecode; - tif->tif_decodestrip = LZMADecode; - tif->tif_decodetile = LZMADecode; - tif->tif_setupencode = LZMASetupEncode; - tif->tif_preencode = LZMAPreEncode; - tif->tif_postencode = LZMAPostEncode; - tif->tif_encoderow = LZMAEncode; - tif->tif_encodestrip = LZMAEncode; - tif->tif_encodetile = LZMAEncode; - tif->tif_cleanup = LZMACleanup; - /* - * Setup predictor setup. - */ - (void) TIFFPredictorInit(tif); - return 1; + /* + * Install codec methods. + */ + tif->tif_fixuptags = LZMAFixupTags; + tif->tif_setupdecode = LZMASetupDecode; + tif->tif_predecode = LZMAPreDecode; + tif->tif_decoderow = LZMADecode; + tif->tif_decodestrip = LZMADecode; + tif->tif_decodetile = LZMADecode; + tif->tif_setupencode = LZMASetupEncode; + tif->tif_preencode = LZMAPreEncode; + tif->tif_postencode = LZMAPostEncode; + tif->tif_encoderow = LZMAEncode; + tif->tif_encodestrip = LZMAEncode; + tif->tif_encodetile = LZMAEncode; + tif->tif_cleanup = LZMACleanup; + /* + * Setup predictor setup. + */ + (void) TIFFPredictorInit(tif); + return 1; bad: - TIFFErrorExt(tif->tif_clientdata, module, - "No space for LZMA2 state block"); - return 0; + TIFFErrorExt(tif->tif_clientdata, module, + "No space for LZMA2 state block"); + return 0; } -#endif /* LZMA_SUPORT */ +#endif /* LZMA_SUPPORT */ /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_lzw.c b/3rdparty/libtiff/tif_lzw.c index ea5cac1585..bc8f9c84a6 100644 --- a/3rdparty/libtiff/tif_lzw.c +++ b/3rdparty/libtiff/tif_lzw.c @@ -1,33 +1,33 @@ -/* $Id: tif_lzw.c,v 1.45 2011-04-02 20:54:09 bfriesen Exp $ */ +/* $Id: tif_lzw.c,v 1.57 2017-07-11 10:54:29 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #include "tiffiop.h" #ifdef LZW_SUPPORT /* - * TIFF Library. + * TIFF Library. * Rev 5.0 Lempel-Ziv & Welch Compression Support * * This code is derived from the compress program whose code is @@ -89,15 +89,15 @@ * state block must be first in this data structure. */ typedef struct { - TIFFPredictorState predict; /* predictor super class */ + TIFFPredictorState predict; /* predictor super class */ - unsigned short nbits; /* # of bits/code */ - unsigned short maxcode; /* maximum code for lzw_nbits */ - unsigned short free_ent; /* next free entry in hash table */ - long nextdata; /* next bits of i/o */ - long nextbits; /* # of valid bits in lzw_nextdata */ + unsigned short nbits; /* # of bits/code */ + unsigned short maxcode; /* maximum code for lzw_nbits */ + unsigned short free_ent; /* next free entry in hash table */ + unsigned long nextdata; /* next bits of i/o */ + long nextbits; /* # of valid bits in lzw_nextdata */ - int rw_mode; /* preserve rw_mode from init */ + int rw_mode; /* preserve rw_mode from init */ } LZWBaseState; #define lzw_nbits base.nbits @@ -111,47 +111,47 @@ typedef struct { */ typedef uint16 hcode_t; /* codes fit in 16 bits */ typedef struct { - long hash; - hcode_t code; + long hash; + hcode_t code; } hash_t; /* * Decoding-specific state. */ typedef struct code_ent { - struct code_ent *next; - unsigned short length; /* string len, including this token */ - unsigned char value; /* data value */ - unsigned char firstchar; /* first token of string */ + struct code_ent *next; + unsigned short length; /* string len, including this token */ + unsigned char value; /* data value */ + unsigned char firstchar; /* first token of string */ } code_t; typedef int (*decodeFunc)(TIFF*, uint8*, tmsize_t, uint16); typedef struct { - LZWBaseState base; + LZWBaseState base; - /* Decoding specific data */ - long dec_nbitsmask; /* lzw_nbits 1 bits, right adjusted */ - long dec_restart; /* restart count */ + /* Decoding specific data */ + long dec_nbitsmask; /* lzw_nbits 1 bits, right adjusted */ + long dec_restart; /* restart count */ #ifdef LZW_CHECKEOS - uint64 dec_bitsleft; /* available bits in raw data */ + uint64 dec_bitsleft; /* available bits in raw data */ #endif - decodeFunc dec_decode; /* regular or backwards compatible */ - code_t* dec_codep; /* current recognized code */ - code_t* dec_oldcodep; /* previously recognized code */ - code_t* dec_free_entp; /* next free entry */ - code_t* dec_maxcodep; /* max available entry */ - code_t* dec_codetab; /* kept separate for small machines */ + decodeFunc dec_decode; /* regular or backwards compatible */ + code_t* dec_codep; /* current recognized code */ + code_t* dec_oldcodep; /* previously recognized code */ + code_t* dec_free_entp; /* next free entry */ + code_t* dec_maxcodep; /* max available entry */ + code_t* dec_codetab; /* kept separate for small machines */ - /* Encoding specific data */ - int enc_oldcode; /* last code encountered */ - long enc_checkpoint; /* point at which to clear table */ + /* Encoding specific data */ + int enc_oldcode; /* last code encountered */ + long enc_checkpoint; /* point at which to clear table */ #define CHECK_GAP 10000 /* enc_ratio check interval */ - long enc_ratio; /* current compression ratio */ - long enc_incount; /* (input) data bytes encoded */ - long enc_outcount; /* encoded (output) bytes */ - uint8* enc_rawlimit; /* bound on tif_rawdata buffer */ - hash_t* enc_hashtab; /* kept separate for small machines */ + long enc_ratio; /* current compression ratio */ + long enc_incount; /* (input) data bytes encoded */ + long enc_outcount; /* encoded (output) bytes */ + uint8* enc_rawlimit; /* bound on tif_rawdata buffer */ + hash_t* enc_hashtab; /* kept separate for small machines */ } LZWCodecState; #define LZWState(tif) ((LZWBaseState*) (tif)->tif_data) @@ -174,15 +174,15 @@ static void cl_hash(LZWCodecState*); * strip is suppose to be terminated with CODE_EOI. */ #define NextCode(_tif, _sp, _bp, _code, _get) { \ - if ((_sp)->dec_bitsleft < (uint64)nbits) { \ - TIFFWarningExt(_tif->tif_clientdata, module, \ - "LZWDecode: Strip %d not terminated with EOI code", \ - _tif->tif_curstrip); \ - _code = CODE_EOI; \ - } else { \ - _get(_sp,_bp,_code); \ - (_sp)->dec_bitsleft -= nbits; \ - } \ + if ((_sp)->dec_bitsleft < (uint64)nbits) { \ + TIFFWarningExt(_tif->tif_clientdata, module, \ + "LZWDecode: Strip %d not terminated with EOI code", \ + _tif->tif_curstrip); \ + _code = CODE_EOI; \ + } else { \ + _get(_sp,_bp,_code); \ + (_sp)->dec_bitsleft -= nbits; \ + } \ } #else #define NextCode(tif, sp, bp, code, get) get(sp, bp, code) @@ -191,67 +191,67 @@ static void cl_hash(LZWCodecState*); static int LZWFixupTags(TIFF* tif) { - (void) tif; - return (1); + (void) tif; + return (1); } static int LZWSetupDecode(TIFF* tif) { - static const char module[] = "LZWSetupDecode"; - LZWCodecState* sp = DecoderState(tif); - int code; + static const char module[] = "LZWSetupDecode"; + LZWCodecState* sp = DecoderState(tif); + int code; - if( sp == NULL ) - { - /* - * Allocate state block so tag methods have storage to record - * values. - */ - tif->tif_data = (uint8*) _TIFFmalloc(sizeof(LZWCodecState)); - if (tif->tif_data == NULL) - { - TIFFErrorExt(tif->tif_clientdata, module, "No space for LZW state block"); - return (0); - } + if( sp == NULL ) + { + /* + * Allocate state block so tag methods have storage to record + * values. + */ + tif->tif_data = (uint8*) _TIFFmalloc(sizeof(LZWCodecState)); + if (tif->tif_data == NULL) + { + TIFFErrorExt(tif->tif_clientdata, module, "No space for LZW state block"); + return (0); + } - DecoderState(tif)->dec_codetab = NULL; - DecoderState(tif)->dec_decode = NULL; + DecoderState(tif)->dec_codetab = NULL; + DecoderState(tif)->dec_decode = NULL; - /* - * Setup predictor setup. - */ - (void) TIFFPredictorInit(tif); + /* + * Setup predictor setup. + */ + (void) TIFFPredictorInit(tif); - sp = DecoderState(tif); - } + sp = DecoderState(tif); + } - assert(sp != NULL); + assert(sp != NULL); - if (sp->dec_codetab == NULL) { - sp->dec_codetab = (code_t*)_TIFFmalloc(CSIZE*sizeof (code_t)); - if (sp->dec_codetab == NULL) { - TIFFErrorExt(tif->tif_clientdata, module, - "No space for LZW code table"); - return (0); - } - /* - * Pre-load the table. - */ - code = 255; - do { - sp->dec_codetab[code].value = code; - sp->dec_codetab[code].firstchar = code; - sp->dec_codetab[code].length = 1; - sp->dec_codetab[code].next = NULL; - } while (code--); - /* - * Zero-out the unused entries + if (sp->dec_codetab == NULL) { + sp->dec_codetab = (code_t*)_TIFFmalloc(CSIZE*sizeof (code_t)); + if (sp->dec_codetab == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, + "No space for LZW code table"); + return (0); + } + /* + * Pre-load the table. + */ + code = 255; + do { + sp->dec_codetab[code].value = (unsigned char)code; + sp->dec_codetab[code].firstchar = (unsigned char)code; + sp->dec_codetab[code].length = 1; + sp->dec_codetab[code].next = NULL; + } while (code--); + /* + * Zero-out the unused entries */ _TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0, - (CODE_FIRST - CODE_CLEAR) * sizeof (code_t)); - } - return (1); + (CODE_FIRST - CODE_CLEAR) * sizeof (code_t)); + } + return (1); } /* @@ -260,307 +260,322 @@ LZWSetupDecode(TIFF* tif) static int LZWPreDecode(TIFF* tif, uint16 s) { - static const char module[] = "LZWPreDecode"; - LZWCodecState *sp = DecoderState(tif); + static const char module[] = "LZWPreDecode"; + LZWCodecState *sp = DecoderState(tif); - (void) s; - assert(sp != NULL); - if( sp->dec_codetab == NULL ) + (void) s; + assert(sp != NULL); + if( sp->dec_codetab == NULL ) { tif->tif_setupdecode( tif ); + if( sp->dec_codetab == NULL ) + return (0); } - /* - * Check for old bit-reversed codes. - */ - if (tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) { + /* + * Check for old bit-reversed codes. + */ + if (tif->tif_rawcc >= 2 && + tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) { #ifdef LZW_COMPAT - if (!sp->dec_decode) { - TIFFWarningExt(tif->tif_clientdata, module, - "Old-style LZW codes, convert file"); - /* - * Override default decoding methods with - * ones that deal with the old coding. - * Otherwise the predictor versions set - * above will call the compatibility routines - * through the dec_decode method. - */ - tif->tif_decoderow = LZWDecodeCompat; - tif->tif_decodestrip = LZWDecodeCompat; - tif->tif_decodetile = LZWDecodeCompat; - /* - * If doing horizontal differencing, must - * re-setup the predictor logic since we - * switched the basic decoder methods... - */ - (*tif->tif_setupdecode)(tif); - sp->dec_decode = LZWDecodeCompat; - } - sp->lzw_maxcode = MAXCODE(BITS_MIN); + if (!sp->dec_decode) { + TIFFWarningExt(tif->tif_clientdata, module, + "Old-style LZW codes, convert file"); + /* + * Override default decoding methods with + * ones that deal with the old coding. + * Otherwise the predictor versions set + * above will call the compatibility routines + * through the dec_decode method. + */ + tif->tif_decoderow = LZWDecodeCompat; + tif->tif_decodestrip = LZWDecodeCompat; + tif->tif_decodetile = LZWDecodeCompat; + /* + * If doing horizontal differencing, must + * re-setup the predictor logic since we + * switched the basic decoder methods... + */ + (*tif->tif_setupdecode)(tif); + sp->dec_decode = LZWDecodeCompat; + } + sp->lzw_maxcode = MAXCODE(BITS_MIN); #else /* !LZW_COMPAT */ - if (!sp->dec_decode) { - TIFFErrorExt(tif->tif_clientdata, module, - "Old-style LZW codes not supported"); - sp->dec_decode = LZWDecode; - } - return (0); + if (!sp->dec_decode) { + TIFFErrorExt(tif->tif_clientdata, module, + "Old-style LZW codes not supported"); + sp->dec_decode = LZWDecode; + } + return (0); #endif/* !LZW_COMPAT */ - } else { - sp->lzw_maxcode = MAXCODE(BITS_MIN)-1; - sp->dec_decode = LZWDecode; - } - sp->lzw_nbits = BITS_MIN; - sp->lzw_nextbits = 0; - sp->lzw_nextdata = 0; + } else { + sp->lzw_maxcode = MAXCODE(BITS_MIN)-1; + sp->dec_decode = LZWDecode; + } + sp->lzw_nbits = BITS_MIN; + sp->lzw_nextbits = 0; + sp->lzw_nextdata = 0; - sp->dec_restart = 0; - sp->dec_nbitsmask = MAXCODE(BITS_MIN); + sp->dec_restart = 0; + sp->dec_nbitsmask = MAXCODE(BITS_MIN); #ifdef LZW_CHECKEOS - sp->dec_bitsleft = ((uint64)tif->tif_rawcc) << 3; + sp->dec_bitsleft = 0; #endif - sp->dec_free_entp = sp->dec_codetab + CODE_FIRST; - /* - * Zero entries that are not yet filled in. We do - * this to guard against bogus input data that causes - * us to index into undefined entries. If you can - * come up with a way to safely bounds-check input codes - * while decoding then you can remove this operation. - */ - _TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t)); - sp->dec_oldcodep = &sp->dec_codetab[-1]; - sp->dec_maxcodep = &sp->dec_codetab[sp->dec_nbitsmask-1]; - return (1); + sp->dec_free_entp = sp->dec_codetab + CODE_FIRST; + /* + * Zero entries that are not yet filled in. We do + * this to guard against bogus input data that causes + * us to index into undefined entries. If you can + * come up with a way to safely bounds-check input codes + * while decoding then you can remove this operation. + */ + _TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t)); + sp->dec_oldcodep = &sp->dec_codetab[-1]; + sp->dec_maxcodep = &sp->dec_codetab[sp->dec_nbitsmask-1]; + return (1); } /* * Decode a "hunk of data". */ #define GetNextCode(sp, bp, code) { \ - nextdata = (nextdata<<8) | *(bp)++; \ - nextbits += 8; \ - if (nextbits < nbits) { \ - nextdata = (nextdata<<8) | *(bp)++; \ - nextbits += 8; \ - } \ - code = (hcode_t)((nextdata >> (nextbits-nbits)) & nbitsmask); \ - nextbits -= nbits; \ + nextdata = (nextdata<<8) | *(bp)++; \ + nextbits += 8; \ + if (nextbits < nbits) { \ + nextdata = (nextdata<<8) | *(bp)++; \ + nextbits += 8; \ + } \ + code = (hcode_t)((nextdata >> (nextbits-nbits)) & nbitsmask); \ + nextbits -= nbits; \ } static void codeLoop(TIFF* tif, const char* module) { - TIFFErrorExt(tif->tif_clientdata, module, - "Bogus encoding, loop in the code table; scanline %d", - tif->tif_row); + TIFFErrorExt(tif->tif_clientdata, module, + "Bogus encoding, loop in the code table; scanline %d", + tif->tif_row); } static int LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) { - static const char module[] = "LZWDecode"; - LZWCodecState *sp = DecoderState(tif); - char *op = (char*) op0; - long occ = (long) occ0; - char *tp; - unsigned char *bp; - hcode_t code; - int len; - long nbits, nextbits, nextdata, nbitsmask; - code_t *codep, *free_entp, *maxcodep, *oldcodep; + static const char module[] = "LZWDecode"; + LZWCodecState *sp = DecoderState(tif); + char *op = (char*) op0; + long occ = (long) occ0; + char *tp; + unsigned char *bp; + hcode_t code; + int len; + long nbits, nextbits, nbitsmask; + unsigned long nextdata; + code_t *codep, *free_entp, *maxcodep, *oldcodep; - (void) s; - assert(sp != NULL); + (void) s; + assert(sp != NULL); assert(sp->dec_codetab != NULL); - /* - Fail if value does not fit in long. - */ - if ((tmsize_t) occ != occ0) - return (0); - /* - * Restart interrupted output operation. - */ - if (sp->dec_restart) { - long residue; + /* + Fail if value does not fit in long. + */ + if ((tmsize_t) occ != occ0) + return (0); + /* + * Restart interrupted output operation. + */ + if (sp->dec_restart) { + long residue; - codep = sp->dec_codep; - residue = codep->length - sp->dec_restart; - if (residue > occ) { - /* - * Residue from previous decode is sufficient - * to satisfy decode request. Skip to the - * start of the decoded string, place decoded - * values in the output buffer, and return. - */ - sp->dec_restart += occ; - do { - codep = codep->next; - } while (--residue > occ && codep); - if (codep) { - tp = op + occ; - do { - *--tp = codep->value; - codep = codep->next; - } while (--occ && codep); - } - return (1); - } - /* - * Residue satisfies only part of the decode request. - */ - op += residue, occ -= residue; - tp = op; - do { - int t; - --tp; - t = codep->value; - codep = codep->next; - *tp = t; - } while (--residue && codep); - sp->dec_restart = 0; - } + codep = sp->dec_codep; + residue = codep->length - sp->dec_restart; + if (residue > occ) { + /* + * Residue from previous decode is sufficient + * to satisfy decode request. Skip to the + * start of the decoded string, place decoded + * values in the output buffer, and return. + */ + sp->dec_restart += occ; + do { + codep = codep->next; + } while (--residue > occ && codep); + if (codep) { + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ && codep); + } + return (1); + } + /* + * Residue satisfies only part of the decode request. + */ + op += residue; + occ -= residue; + tp = op; + do { + int t; + --tp; + t = codep->value; + codep = codep->next; + *tp = (char)t; + } while (--residue && codep); + sp->dec_restart = 0; + } - bp = (unsigned char *)tif->tif_rawcp; - nbits = sp->lzw_nbits; - nextdata = sp->lzw_nextdata; - nextbits = sp->lzw_nextbits; - nbitsmask = sp->dec_nbitsmask; - oldcodep = sp->dec_oldcodep; - free_entp = sp->dec_free_entp; - maxcodep = sp->dec_maxcodep; - - while (occ > 0) { - NextCode(tif, sp, bp, code, GetNextCode); - if (code == CODE_EOI) - break; - if (code == CODE_CLEAR) { - free_entp = sp->dec_codetab + CODE_FIRST; - _TIFFmemset(free_entp, 0, - (CSIZE - CODE_FIRST) * sizeof (code_t)); - nbits = BITS_MIN; - nbitsmask = MAXCODE(BITS_MIN); - maxcodep = sp->dec_codetab + nbitsmask-1; - NextCode(tif, sp, bp, code, GetNextCode); - if (code == CODE_EOI) - break; - if (code >= CODE_CLEAR) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "LZWDecode: Corrupted LZW table at scanline %d", - tif->tif_row); - return (0); - } - *op++ = (char)code, occ--; - oldcodep = sp->dec_codetab + code; - continue; - } - codep = sp->dec_codetab + code; - - /* - * Add the new entry to the code table. - */ - if (free_entp < &sp->dec_codetab[0] || - free_entp >= &sp->dec_codetab[CSIZE]) { - TIFFErrorExt(tif->tif_clientdata, module, - "Corrupted LZW table at scanline %d", - tif->tif_row); - return (0); - } - - free_entp->next = oldcodep; - if (free_entp->next < &sp->dec_codetab[0] || - free_entp->next >= &sp->dec_codetab[CSIZE]) { - TIFFErrorExt(tif->tif_clientdata, module, - "Corrupted LZW table at scanline %d", - tif->tif_row); - return (0); - } - free_entp->firstchar = free_entp->next->firstchar; - free_entp->length = free_entp->next->length+1; - free_entp->value = (codep < free_entp) ? - codep->firstchar : free_entp->firstchar; - if (++free_entp > maxcodep) { - if (++nbits > BITS_MAX) /* should not happen */ - nbits = BITS_MAX; - nbitsmask = MAXCODE(nbits); - maxcodep = sp->dec_codetab + nbitsmask-1; - } - oldcodep = codep; - if (code >= 256) { - /* - * Code maps to a string, copy string - * value to output (written in reverse). - */ - if(codep->length == 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "Wrong length of decoded string: " - "data probably corrupted at scanline %d", - tif->tif_row); - return (0); - } - if (codep->length > occ) { - /* - * String is too long for decode buffer, - * locate portion that will fit, copy to - * the decode buffer, and setup restart - * logic for the next decoding call. - */ - sp->dec_codep = codep; - do { - codep = codep->next; - } while (codep && codep->length > occ); - if (codep) { - sp->dec_restart = (long)occ; - tp = op + occ; - do { - *--tp = codep->value; - codep = codep->next; - } while (--occ && codep); - if (codep) - codeLoop(tif, module); - } - break; - } - len = codep->length; - tp = op + len; - do { - int t; - --tp; - t = codep->value; - codep = codep->next; - *tp = t; - } while (codep && tp > op); - if (codep) { - codeLoop(tif, module); - break; - } - assert(occ >= len); - op += len, occ -= len; - } else - *op++ = (char)code, occ--; - } - - tif->tif_rawcp = (uint8*) bp; - sp->lzw_nbits = (unsigned short) nbits; - sp->lzw_nextdata = nextdata; - sp->lzw_nextbits = nextbits; - sp->dec_nbitsmask = nbitsmask; - sp->dec_oldcodep = oldcodep; - sp->dec_free_entp = free_entp; - sp->dec_maxcodep = maxcodep; - - if (occ > 0) { -#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at scanline %d (short %I64d bytes)", - tif->tif_row, (unsigned __int64) occ); -#else - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at scanline %d (short %llu bytes)", - tif->tif_row, (unsigned long long) occ); + bp = (unsigned char *)tif->tif_rawcp; +#ifdef LZW_CHECKEOS + sp->dec_bitsleft = (((uint64)tif->tif_rawcc) << 3); #endif - return (0); - } - return (1); + nbits = sp->lzw_nbits; + nextdata = sp->lzw_nextdata; + nextbits = sp->lzw_nextbits; + nbitsmask = sp->dec_nbitsmask; + oldcodep = sp->dec_oldcodep; + free_entp = sp->dec_free_entp; + maxcodep = sp->dec_maxcodep; + + while (occ > 0) { + NextCode(tif, sp, bp, code, GetNextCode); + if (code == CODE_EOI) + break; + if (code == CODE_CLEAR) { + do { + free_entp = sp->dec_codetab + CODE_FIRST; + _TIFFmemset(free_entp, 0, + (CSIZE - CODE_FIRST) * sizeof (code_t)); + nbits = BITS_MIN; + nbitsmask = MAXCODE(BITS_MIN); + maxcodep = sp->dec_codetab + nbitsmask-1; + NextCode(tif, sp, bp, code, GetNextCode); + } while (code == CODE_CLEAR); /* consecutive CODE_CLEAR codes */ + if (code == CODE_EOI) + break; + if (code > CODE_CLEAR) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecode: Corrupted LZW table at scanline %d", + tif->tif_row); + return (0); + } + *op++ = (char)code; + occ--; + oldcodep = sp->dec_codetab + code; + continue; + } + codep = sp->dec_codetab + code; + + /* + * Add the new entry to the code table. + */ + if (free_entp < &sp->dec_codetab[0] || + free_entp >= &sp->dec_codetab[CSIZE]) { + TIFFErrorExt(tif->tif_clientdata, module, + "Corrupted LZW table at scanline %d", + tif->tif_row); + return (0); + } + + free_entp->next = oldcodep; + if (free_entp->next < &sp->dec_codetab[0] || + free_entp->next >= &sp->dec_codetab[CSIZE]) { + TIFFErrorExt(tif->tif_clientdata, module, + "Corrupted LZW table at scanline %d", + tif->tif_row); + return (0); + } + free_entp->firstchar = free_entp->next->firstchar; + free_entp->length = free_entp->next->length+1; + free_entp->value = (codep < free_entp) ? + codep->firstchar : free_entp->firstchar; + if (++free_entp > maxcodep) { + if (++nbits > BITS_MAX) /* should not happen */ + nbits = BITS_MAX; + nbitsmask = MAXCODE(nbits); + maxcodep = sp->dec_codetab + nbitsmask-1; + } + oldcodep = codep; + if (code >= 256) { + /* + * Code maps to a string, copy string + * value to output (written in reverse). + */ + if(codep->length == 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Wrong length of decoded string: " + "data probably corrupted at scanline %d", + tif->tif_row); + return (0); + } + if (codep->length > occ) { + /* + * String is too long for decode buffer, + * locate portion that will fit, copy to + * the decode buffer, and setup restart + * logic for the next decoding call. + */ + sp->dec_codep = codep; + do { + codep = codep->next; + } while (codep && codep->length > occ); + if (codep) { + sp->dec_restart = (long)occ; + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ && codep); + if (codep) + codeLoop(tif, module); + } + break; + } + len = codep->length; + tp = op + len; + do { + int t; + --tp; + t = codep->value; + codep = codep->next; + *tp = (char)t; + } while (codep && tp > op); + if (codep) { + codeLoop(tif, module); + break; + } + assert(occ >= len); + op += len; + occ -= len; + } else { + *op++ = (char)code; + occ--; + } + } + + tif->tif_rawcc -= (tmsize_t)( (uint8*) bp - tif->tif_rawcp ); + tif->tif_rawcp = (uint8*) bp; + sp->lzw_nbits = (unsigned short) nbits; + sp->lzw_nextdata = nextdata; + sp->lzw_nextbits = nextbits; + sp->dec_nbitsmask = nbitsmask; + sp->dec_oldcodep = oldcodep; + sp->dec_free_entp = free_entp; + sp->dec_maxcodep = maxcodep; + + if (occ > 0) { +#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at scanline %d (short %I64d bytes)", + tif->tif_row, (unsigned __int64) occ); +#else + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at scanline %d (short %llu bytes)", + tif->tif_row, (unsigned long long) occ); +#endif + return (0); + } + return (1); } #ifdef LZW_COMPAT @@ -568,203 +583,214 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) * Decode a "hunk of data" for old images. */ #define GetNextCodeCompat(sp, bp, code) { \ - nextdata |= (unsigned long) *(bp)++ << nextbits; \ - nextbits += 8; \ - if (nextbits < nbits) { \ - nextdata |= (unsigned long) *(bp)++ << nextbits;\ - nextbits += 8; \ - } \ - code = (hcode_t)(nextdata & nbitsmask); \ - nextdata >>= nbits; \ - nextbits -= nbits; \ + nextdata |= (unsigned long) *(bp)++ << nextbits; \ + nextbits += 8; \ + if (nextbits < nbits) { \ + nextdata |= (unsigned long) *(bp)++ << nextbits;\ + nextbits += 8; \ + } \ + code = (hcode_t)(nextdata & nbitsmask); \ + nextdata >>= nbits; \ + nextbits -= nbits; \ } static int LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) { - static const char module[] = "LZWDecodeCompat"; - LZWCodecState *sp = DecoderState(tif); - char *op = (char*) op0; - long occ = (long) occ0; - char *tp; - unsigned char *bp; - int code, nbits; - long nextbits, nextdata, nbitsmask; - code_t *codep, *free_entp, *maxcodep, *oldcodep; + static const char module[] = "LZWDecodeCompat"; + LZWCodecState *sp = DecoderState(tif); + char *op = (char*) op0; + long occ = (long) occ0; + char *tp; + unsigned char *bp; + int code, nbits; + long nextbits, nextdata, nbitsmask; + code_t *codep, *free_entp, *maxcodep, *oldcodep; - (void) s; - assert(sp != NULL); + (void) s; + assert(sp != NULL); - /* - Fail if value does not fit in long. - */ - if ((tmsize_t) occ != occ0) - return (0); + /* + Fail if value does not fit in long. + */ + if ((tmsize_t) occ != occ0) + return (0); - /* - * Restart interrupted output operation. - */ - if (sp->dec_restart) { - long residue; + /* + * Restart interrupted output operation. + */ + if (sp->dec_restart) { + long residue; - codep = sp->dec_codep; - residue = codep->length - sp->dec_restart; - if (residue > occ) { - /* - * Residue from previous decode is sufficient - * to satisfy decode request. Skip to the - * start of the decoded string, place decoded - * values in the output buffer, and return. - */ - sp->dec_restart += occ; - do { - codep = codep->next; - } while (--residue > occ); - tp = op + occ; - do { - *--tp = codep->value; - codep = codep->next; - } while (--occ); - return (1); - } - /* - * Residue satisfies only part of the decode request. - */ - op += residue, occ -= residue; - tp = op; - do { - *--tp = codep->value; - codep = codep->next; - } while (--residue); - sp->dec_restart = 0; - } + codep = sp->dec_codep; + residue = codep->length - sp->dec_restart; + if (residue > occ) { + /* + * Residue from previous decode is sufficient + * to satisfy decode request. Skip to the + * start of the decoded string, place decoded + * values in the output buffer, and return. + */ + sp->dec_restart += occ; + do { + codep = codep->next; + } while (--residue > occ); + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ); + return (1); + } + /* + * Residue satisfies only part of the decode request. + */ + op += residue; + occ -= residue; + tp = op; + do { + *--tp = codep->value; + codep = codep->next; + } while (--residue); + sp->dec_restart = 0; + } - bp = (unsigned char *)tif->tif_rawcp; - nbits = sp->lzw_nbits; - nextdata = sp->lzw_nextdata; - nextbits = sp->lzw_nextbits; - nbitsmask = sp->dec_nbitsmask; - oldcodep = sp->dec_oldcodep; - free_entp = sp->dec_free_entp; - maxcodep = sp->dec_maxcodep; - - while (occ > 0) { - NextCode(tif, sp, bp, code, GetNextCodeCompat); - if (code == CODE_EOI) - break; - if (code == CODE_CLEAR) { - free_entp = sp->dec_codetab + CODE_FIRST; - _TIFFmemset(free_entp, 0, - (CSIZE - CODE_FIRST) * sizeof (code_t)); - nbits = BITS_MIN; - nbitsmask = MAXCODE(BITS_MIN); - maxcodep = sp->dec_codetab + nbitsmask; - NextCode(tif, sp, bp, code, GetNextCodeCompat); - if (code == CODE_EOI) - break; - if (code >= CODE_CLEAR) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "LZWDecode: Corrupted LZW table at scanline %d", - tif->tif_row); - return (0); - } - *op++ = code, occ--; - oldcodep = sp->dec_codetab + code; - continue; - } - codep = sp->dec_codetab + code; - - /* - * Add the new entry to the code table. - */ - if (free_entp < &sp->dec_codetab[0] || - free_entp >= &sp->dec_codetab[CSIZE]) { - TIFFErrorExt(tif->tif_clientdata, module, - "Corrupted LZW table at scanline %d", tif->tif_row); - return (0); - } - - free_entp->next = oldcodep; - if (free_entp->next < &sp->dec_codetab[0] || - free_entp->next >= &sp->dec_codetab[CSIZE]) { - TIFFErrorExt(tif->tif_clientdata, module, - "Corrupted LZW table at scanline %d", tif->tif_row); - return (0); - } - free_entp->firstchar = free_entp->next->firstchar; - free_entp->length = free_entp->next->length+1; - free_entp->value = (codep < free_entp) ? - codep->firstchar : free_entp->firstchar; - if (++free_entp > maxcodep) { - if (++nbits > BITS_MAX) /* should not happen */ - nbits = BITS_MAX; - nbitsmask = MAXCODE(nbits); - maxcodep = sp->dec_codetab + nbitsmask; - } - oldcodep = codep; - if (code >= 256) { - /* - * Code maps to a string, copy string - * value to output (written in reverse). - */ - if(codep->length == 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "Wrong length of decoded " - "string: data probably corrupted at scanline %d", - tif->tif_row); - return (0); - } - if (codep->length > occ) { - /* - * String is too long for decode buffer, - * locate portion that will fit, copy to - * the decode buffer, and setup restart - * logic for the next decoding call. - */ - sp->dec_codep = codep; - do { - codep = codep->next; - } while (codep->length > occ); - sp->dec_restart = occ; - tp = op + occ; - do { - *--tp = codep->value; - codep = codep->next; - } while (--occ); - break; - } - assert(occ >= codep->length); - op += codep->length, occ -= codep->length; - tp = op; - do { - *--tp = codep->value; - } while( (codep = codep->next) != NULL ); - } else - *op++ = code, occ--; - } - - tif->tif_rawcp = (uint8*) bp; - sp->lzw_nbits = nbits; - sp->lzw_nextdata = nextdata; - sp->lzw_nextbits = nextbits; - sp->dec_nbitsmask = nbitsmask; - sp->dec_oldcodep = oldcodep; - sp->dec_free_entp = free_entp; - sp->dec_maxcodep = maxcodep; - - if (occ > 0) { -#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at scanline %d (short %I64d bytes)", - tif->tif_row, (unsigned __int64) occ); -#else - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at scanline %d (short %llu bytes)", - tif->tif_row, (unsigned long long) occ); + bp = (unsigned char *)tif->tif_rawcp; +#ifdef LZW_CHECKEOS + sp->dec_bitsleft = (((uint64)tif->tif_rawcc) << 3); #endif - return (0); - } - return (1); + nbits = sp->lzw_nbits; + nextdata = sp->lzw_nextdata; + nextbits = sp->lzw_nextbits; + nbitsmask = sp->dec_nbitsmask; + oldcodep = sp->dec_oldcodep; + free_entp = sp->dec_free_entp; + maxcodep = sp->dec_maxcodep; + + while (occ > 0) { + NextCode(tif, sp, bp, code, GetNextCodeCompat); + if (code == CODE_EOI) + break; + if (code == CODE_CLEAR) { + do { + free_entp = sp->dec_codetab + CODE_FIRST; + _TIFFmemset(free_entp, 0, + (CSIZE - CODE_FIRST) * sizeof (code_t)); + nbits = BITS_MIN; + nbitsmask = MAXCODE(BITS_MIN); + maxcodep = sp->dec_codetab + nbitsmask; + NextCode(tif, sp, bp, code, GetNextCodeCompat); + } while (code == CODE_CLEAR); /* consecutive CODE_CLEAR codes */ + if (code == CODE_EOI) + break; + if (code > CODE_CLEAR) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "LZWDecode: Corrupted LZW table at scanline %d", + tif->tif_row); + return (0); + } + *op++ = (char)code; + occ--; + oldcodep = sp->dec_codetab + code; + continue; + } + codep = sp->dec_codetab + code; + + /* + * Add the new entry to the code table. + */ + if (free_entp < &sp->dec_codetab[0] || + free_entp >= &sp->dec_codetab[CSIZE]) { + TIFFErrorExt(tif->tif_clientdata, module, + "Corrupted LZW table at scanline %d", tif->tif_row); + return (0); + } + + free_entp->next = oldcodep; + if (free_entp->next < &sp->dec_codetab[0] || + free_entp->next >= &sp->dec_codetab[CSIZE]) { + TIFFErrorExt(tif->tif_clientdata, module, + "Corrupted LZW table at scanline %d", tif->tif_row); + return (0); + } + free_entp->firstchar = free_entp->next->firstchar; + free_entp->length = free_entp->next->length+1; + free_entp->value = (codep < free_entp) ? + codep->firstchar : free_entp->firstchar; + if (++free_entp > maxcodep) { + if (++nbits > BITS_MAX) /* should not happen */ + nbits = BITS_MAX; + nbitsmask = MAXCODE(nbits); + maxcodep = sp->dec_codetab + nbitsmask; + } + oldcodep = codep; + if (code >= 256) { + /* + * Code maps to a string, copy string + * value to output (written in reverse). + */ + if(codep->length == 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Wrong length of decoded " + "string: data probably corrupted at scanline %d", + tif->tif_row); + return (0); + } + if (codep->length > occ) { + /* + * String is too long for decode buffer, + * locate portion that will fit, copy to + * the decode buffer, and setup restart + * logic for the next decoding call. + */ + sp->dec_codep = codep; + do { + codep = codep->next; + } while (codep->length > occ); + sp->dec_restart = occ; + tp = op + occ; + do { + *--tp = codep->value; + codep = codep->next; + } while (--occ); + break; + } + assert(occ >= codep->length); + op += codep->length; + occ -= codep->length; + tp = op; + do { + *--tp = codep->value; + } while( (codep = codep->next) != NULL ); + } else { + *op++ = (char)code; + occ--; + } + } + + tif->tif_rawcc -= (tmsize_t)( (uint8*) bp - tif->tif_rawcp ); + tif->tif_rawcp = (uint8*) bp; + sp->lzw_nbits = (unsigned short)nbits; + sp->lzw_nextdata = nextdata; + sp->lzw_nextbits = nextbits; + sp->dec_nbitsmask = nbitsmask; + sp->dec_oldcodep = oldcodep; + sp->dec_free_entp = free_entp; + sp->dec_maxcodep = maxcodep; + + if (occ > 0) { +#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at scanline %d (short %I64d bytes)", + tif->tif_row, (unsigned __int64) occ); +#else + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at scanline %d (short %llu bytes)", + tif->tif_row, (unsigned long long) occ); +#endif + return (0); + } + return (1); } #endif /* LZW_COMPAT */ @@ -775,17 +801,17 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) static int LZWSetupEncode(TIFF* tif) { - static const char module[] = "LZWSetupEncode"; - LZWCodecState* sp = EncoderState(tif); + static const char module[] = "LZWSetupEncode"; + LZWCodecState* sp = EncoderState(tif); - assert(sp != NULL); - sp->enc_hashtab = (hash_t*) _TIFFmalloc(HSIZE*sizeof (hash_t)); - if (sp->enc_hashtab == NULL) { - TIFFErrorExt(tif->tif_clientdata, module, - "No space for LZW hash table"); - return (0); - } - return (1); + assert(sp != NULL); + sp->enc_hashtab = (hash_t*) _TIFFmalloc(HSIZE*sizeof (hash_t)); + if (sp->enc_hashtab == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, + "No space for LZW hash table"); + return (0); + } + return (1); } /* @@ -794,228 +820,232 @@ LZWSetupEncode(TIFF* tif) static int LZWPreEncode(TIFF* tif, uint16 s) { - LZWCodecState *sp = EncoderState(tif); + LZWCodecState *sp = EncoderState(tif); - (void) s; - assert(sp != NULL); + (void) s; + assert(sp != NULL); - if( sp->enc_hashtab == NULL ) + if( sp->enc_hashtab == NULL ) { tif->tif_setupencode( tif ); } - sp->lzw_nbits = BITS_MIN; - sp->lzw_maxcode = MAXCODE(BITS_MIN); - sp->lzw_free_ent = CODE_FIRST; - sp->lzw_nextbits = 0; - sp->lzw_nextdata = 0; - sp->enc_checkpoint = CHECK_GAP; - sp->enc_ratio = 0; - sp->enc_incount = 0; - sp->enc_outcount = 0; - /* - * The 4 here insures there is space for 2 max-sized - * codes in LZWEncode and LZWPostDecode. - */ - sp->enc_rawlimit = tif->tif_rawdata + tif->tif_rawdatasize-1 - 4; - cl_hash(sp); /* clear hash table */ - sp->enc_oldcode = (hcode_t) -1; /* generates CODE_CLEAR in LZWEncode */ - return (1); + sp->lzw_nbits = BITS_MIN; + sp->lzw_maxcode = MAXCODE(BITS_MIN); + sp->lzw_free_ent = CODE_FIRST; + sp->lzw_nextbits = 0; + sp->lzw_nextdata = 0; + sp->enc_checkpoint = CHECK_GAP; + sp->enc_ratio = 0; + sp->enc_incount = 0; + sp->enc_outcount = 0; + /* + * The 4 here insures there is space for 2 max-sized + * codes in LZWEncode and LZWPostDecode. + */ + sp->enc_rawlimit = tif->tif_rawdata + tif->tif_rawdatasize-1 - 4; + cl_hash(sp); /* clear hash table */ + sp->enc_oldcode = (hcode_t) -1; /* generates CODE_CLEAR in LZWEncode */ + return (1); } #define CALCRATIO(sp, rat) { \ - if (incount > 0x007fffff) { /* NB: shift will overflow */\ - rat = outcount >> 8; \ - rat = (rat == 0 ? 0x7fffffff : incount/rat); \ - } else \ - rat = (incount<<8) / outcount; \ + if (incount > 0x007fffff) { /* NB: shift will overflow */\ + rat = outcount >> 8; \ + rat = (rat == 0 ? 0x7fffffff : incount/rat); \ + } else \ + rat = (incount<<8) / outcount; \ } + +/* Explicit 0xff masking to make icc -check=conversions happy */ #define PutNextCode(op, c) { \ - nextdata = (nextdata << nbits) | c; \ - nextbits += nbits; \ - *op++ = (unsigned char)(nextdata >> (nextbits-8)); \ - nextbits -= 8; \ - if (nextbits >= 8) { \ - *op++ = (unsigned char)(nextdata >> (nextbits-8)); \ - nextbits -= 8; \ - } \ - outcount += nbits; \ + nextdata = (nextdata << nbits) | c; \ + nextbits += nbits; \ + *op++ = (unsigned char)((nextdata >> (nextbits-8))&0xff); \ + nextbits -= 8; \ + if (nextbits >= 8) { \ + *op++ = (unsigned char)((nextdata >> (nextbits-8))&0xff); \ + nextbits -= 8; \ + } \ + outcount += nbits; \ } /* * Encode a chunk of pixels. * - * Uses an open addressing double hashing (no chaining) on the + * Uses an open addressing double hashing (no chaining) on the * prefix code/next character combination. We do a variant of * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's * relatively-prime secondary probe. Here, the modular division - * first probe is gives way to a faster exclusive-or manipulation. + * first probe is gives way to a faster exclusive-or manipulation. * Also do block compression with an adaptive reset, whereby the * code table is cleared when the compression ratio decreases, * but after the table fills. The variable-length output codes * are re-sized at this point, and a CODE_CLEAR is generated - * for the decoder. + * for the decoder. */ static int LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - register LZWCodecState *sp = EncoderState(tif); - register long fcode; - register hash_t *hp; - register int h, c; - hcode_t ent; - long disp; - long incount, outcount, checkpoint; - long nextdata, nextbits; - int free_ent, maxcode, nbits; - uint8* op; - uint8* limit; + register LZWCodecState *sp = EncoderState(tif); + register long fcode; + register hash_t *hp; + register int h, c; + hcode_t ent; + long disp; + long incount, outcount, checkpoint; + unsigned long nextdata; + long nextbits; + int free_ent, maxcode, nbits; + uint8* op; + uint8* limit; - (void) s; - if (sp == NULL) - return (0); + (void) s; + if (sp == NULL) + return (0); assert(sp->enc_hashtab != NULL); - /* - * Load local state. - */ - incount = sp->enc_incount; - outcount = sp->enc_outcount; - checkpoint = sp->enc_checkpoint; - nextdata = sp->lzw_nextdata; - nextbits = sp->lzw_nextbits; - free_ent = sp->lzw_free_ent; - maxcode = sp->lzw_maxcode; - nbits = sp->lzw_nbits; - op = tif->tif_rawcp; - limit = sp->enc_rawlimit; - ent = sp->enc_oldcode; + /* + * Load local state. + */ + incount = sp->enc_incount; + outcount = sp->enc_outcount; + checkpoint = sp->enc_checkpoint; + nextdata = sp->lzw_nextdata; + nextbits = sp->lzw_nextbits; + free_ent = sp->lzw_free_ent; + maxcode = sp->lzw_maxcode; + nbits = sp->lzw_nbits; + op = tif->tif_rawcp; + limit = sp->enc_rawlimit; + ent = (hcode_t)sp->enc_oldcode; - if (ent == (hcode_t) -1 && cc > 0) { - /* - * NB: This is safe because it can only happen - * at the start of a strip where we know there - * is space in the data buffer. - */ - PutNextCode(op, CODE_CLEAR); - ent = *bp++; cc--; incount++; - } - while (cc > 0) { - c = *bp++; cc--; incount++; - fcode = ((long)c << BITS_MAX) + ent; - h = (c << HSHIFT) ^ ent; /* xor hashing */ + if (ent == (hcode_t) -1 && cc > 0) { + /* + * NB: This is safe because it can only happen + * at the start of a strip where we know there + * is space in the data buffer. + */ + PutNextCode(op, CODE_CLEAR); + ent = *bp++; cc--; incount++; + } + while (cc > 0) { + c = *bp++; cc--; incount++; + fcode = ((long)c << BITS_MAX) + ent; + h = (c << HSHIFT) ^ ent; /* xor hashing */ #ifdef _WINDOWS - /* - * Check hash index for an overflow. - */ - if (h >= HSIZE) - h -= HSIZE; + /* + * Check hash index for an overflow. + */ + if (h >= HSIZE) + h -= HSIZE; #endif - hp = &sp->enc_hashtab[h]; - if (hp->hash == fcode) { - ent = hp->code; - continue; - } - if (hp->hash >= 0) { - /* - * Primary hash failed, check secondary hash. - */ - disp = HSIZE - h; - if (h == 0) - disp = 1; - do { - /* - * Avoid pointer arithmetic 'cuz of - * wraparound problems with segments. - */ - if ((h -= disp) < 0) - h += HSIZE; - hp = &sp->enc_hashtab[h]; - if (hp->hash == fcode) { - ent = hp->code; - goto hit; - } - } while (hp->hash >= 0); - } - /* - * New entry, emit code and add to table. - */ - /* - * Verify there is space in the buffer for the code - * and any potential Clear code that might be emitted - * below. The value of limit is setup so that there - * are at least 4 bytes free--room for 2 codes. - */ - if (op > limit) { - tif->tif_rawcc = (tmsize_t)(op - tif->tif_rawdata); - TIFFFlushData1(tif); - op = tif->tif_rawdata; - } - PutNextCode(op, ent); - ent = c; - hp->code = free_ent++; - hp->hash = fcode; - if (free_ent == CODE_MAX-1) { - /* table is full, emit clear code and reset */ - cl_hash(sp); - sp->enc_ratio = 0; - incount = 0; - outcount = 0; - free_ent = CODE_FIRST; - PutNextCode(op, CODE_CLEAR); - nbits = BITS_MIN; - maxcode = MAXCODE(BITS_MIN); - } else { - /* - * If the next entry is going to be too big for - * the code size, then increase it, if possible. - */ - if (free_ent > maxcode) { - nbits++; - assert(nbits <= BITS_MAX); - maxcode = (int) MAXCODE(nbits); - } else if (incount >= checkpoint) { - long rat; - /* - * Check compression ratio and, if things seem - * to be slipping, clear the hash table and - * reset state. The compression ratio is a - * 24+8-bit fractional number. - */ - checkpoint = incount+CHECK_GAP; - CALCRATIO(sp, rat); - if (rat <= sp->enc_ratio) { - cl_hash(sp); - sp->enc_ratio = 0; - incount = 0; - outcount = 0; - free_ent = CODE_FIRST; - PutNextCode(op, CODE_CLEAR); - nbits = BITS_MIN; - maxcode = MAXCODE(BITS_MIN); - } else - sp->enc_ratio = rat; - } - } - hit: - ; - } + hp = &sp->enc_hashtab[h]; + if (hp->hash == fcode) { + ent = hp->code; + continue; + } + if (hp->hash >= 0) { + /* + * Primary hash failed, check secondary hash. + */ + disp = HSIZE - h; + if (h == 0) + disp = 1; + do { + /* + * Avoid pointer arithmetic because of + * wraparound problems with segments. + */ + if ((h -= disp) < 0) + h += HSIZE; + hp = &sp->enc_hashtab[h]; + if (hp->hash == fcode) { + ent = hp->code; + goto hit; + } + } while (hp->hash >= 0); + } + /* + * New entry, emit code and add to table. + */ + /* + * Verify there is space in the buffer for the code + * and any potential Clear code that might be emitted + * below. The value of limit is setup so that there + * are at least 4 bytes free--room for 2 codes. + */ + if (op > limit) { + tif->tif_rawcc = (tmsize_t)(op - tif->tif_rawdata); + if( !TIFFFlushData1(tif) ) + return 0; + op = tif->tif_rawdata; + } + PutNextCode(op, ent); + ent = (hcode_t)c; + hp->code = (hcode_t)(free_ent++); + hp->hash = fcode; + if (free_ent == CODE_MAX-1) { + /* table is full, emit clear code and reset */ + cl_hash(sp); + sp->enc_ratio = 0; + incount = 0; + outcount = 0; + free_ent = CODE_FIRST; + PutNextCode(op, CODE_CLEAR); + nbits = BITS_MIN; + maxcode = MAXCODE(BITS_MIN); + } else { + /* + * If the next entry is going to be too big for + * the code size, then increase it, if possible. + */ + if (free_ent > maxcode) { + nbits++; + assert(nbits <= BITS_MAX); + maxcode = (int) MAXCODE(nbits); + } else if (incount >= checkpoint) { + long rat; + /* + * Check compression ratio and, if things seem + * to be slipping, clear the hash table and + * reset state. The compression ratio is a + * 24+8-bit fractional number. + */ + checkpoint = incount+CHECK_GAP; + CALCRATIO(sp, rat); + if (rat <= sp->enc_ratio) { + cl_hash(sp); + sp->enc_ratio = 0; + incount = 0; + outcount = 0; + free_ent = CODE_FIRST; + PutNextCode(op, CODE_CLEAR); + nbits = BITS_MIN; + maxcode = MAXCODE(BITS_MIN); + } else + sp->enc_ratio = rat; + } + } + hit: + ; + } - /* - * Restore global state. - */ - sp->enc_incount = incount; - sp->enc_outcount = outcount; - sp->enc_checkpoint = checkpoint; - sp->enc_oldcode = ent; - sp->lzw_nextdata = nextdata; - sp->lzw_nextbits = nextbits; - sp->lzw_free_ent = free_ent; - sp->lzw_maxcode = maxcode; - sp->lzw_nbits = nbits; - tif->tif_rawcp = op; - return (1); + /* + * Restore global state. + */ + sp->enc_incount = incount; + sp->enc_outcount = outcount; + sp->enc_checkpoint = checkpoint; + sp->enc_oldcode = ent; + sp->lzw_nextdata = nextdata; + sp->lzw_nextbits = nextbits; + sp->lzw_free_ent = (unsigned short)free_ent; + sp->lzw_maxcode = (unsigned short)maxcode; + sp->lzw_nbits = (unsigned short)nbits; + tif->tif_rawcp = op; + return (1); } /* @@ -1025,27 +1055,48 @@ LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) static int LZWPostEncode(TIFF* tif) { - register LZWCodecState *sp = EncoderState(tif); - uint8* op = tif->tif_rawcp; - long nextbits = sp->lzw_nextbits; - long nextdata = sp->lzw_nextdata; - long outcount = sp->enc_outcount; - int nbits = sp->lzw_nbits; + register LZWCodecState *sp = EncoderState(tif); + uint8* op = tif->tif_rawcp; + long nextbits = sp->lzw_nextbits; + unsigned long nextdata = sp->lzw_nextdata; + long outcount = sp->enc_outcount; + int nbits = sp->lzw_nbits; - if (op > sp->enc_rawlimit) { - tif->tif_rawcc = (tmsize_t)(op - tif->tif_rawdata); - TIFFFlushData1(tif); - op = tif->tif_rawdata; - } - if (sp->enc_oldcode != (hcode_t) -1) { - PutNextCode(op, sp->enc_oldcode); - sp->enc_oldcode = (hcode_t) -1; - } - PutNextCode(op, CODE_EOI); - if (nextbits > 0) - *op++ = (unsigned char)(nextdata << (8-nextbits)); - tif->tif_rawcc = (tmsize_t)(op - tif->tif_rawdata); - return (1); + if (op > sp->enc_rawlimit) { + tif->tif_rawcc = (tmsize_t)(op - tif->tif_rawdata); + if( !TIFFFlushData1(tif) ) + return 0; + op = tif->tif_rawdata; + } + if (sp->enc_oldcode != (hcode_t) -1) { + int free_ent = sp->lzw_free_ent; + + PutNextCode(op, sp->enc_oldcode); + sp->enc_oldcode = (hcode_t) -1; + free_ent ++; + + if (free_ent == CODE_MAX-1) { + /* table is full, emit clear code and reset */ + outcount = 0; + PutNextCode(op, CODE_CLEAR); + nbits = BITS_MIN; + } else { + /* + * If the next entry is going to be too big for + * the code size, then increase it, if possible. + */ + if (free_ent > sp->lzw_maxcode) { + nbits++; + assert(nbits <= BITS_MAX); + } + } + } + PutNextCode(op, CODE_EOI); + /* Explicit 0xff masking to make icc -check=conversions happy */ + if (nextbits > 0) + *op++ = (unsigned char)((nextdata << (8-nextbits))&0xff); + tif->tif_rawcc = (tmsize_t)(op - tif->tif_rawdata); + return (1); } /* @@ -1054,85 +1105,85 @@ LZWPostEncode(TIFF* tif) static void cl_hash(LZWCodecState* sp) { - register hash_t *hp = &sp->enc_hashtab[HSIZE-1]; - register long i = HSIZE-8; + register hash_t *hp = &sp->enc_hashtab[HSIZE-1]; + register long i = HSIZE-8; - do { - i -= 8; - hp[-7].hash = -1; - hp[-6].hash = -1; - hp[-5].hash = -1; - hp[-4].hash = -1; - hp[-3].hash = -1; - hp[-2].hash = -1; - hp[-1].hash = -1; - hp[ 0].hash = -1; - hp -= 8; - } while (i >= 0); - for (i += 8; i > 0; i--, hp--) - hp->hash = -1; + do { + i -= 8; + hp[-7].hash = -1; + hp[-6].hash = -1; + hp[-5].hash = -1; + hp[-4].hash = -1; + hp[-3].hash = -1; + hp[-2].hash = -1; + hp[-1].hash = -1; + hp[ 0].hash = -1; + hp -= 8; + } while (i >= 0); + for (i += 8; i > 0; i--, hp--) + hp->hash = -1; } static void LZWCleanup(TIFF* tif) { - (void)TIFFPredictorCleanup(tif); + (void)TIFFPredictorCleanup(tif); - assert(tif->tif_data != 0); + assert(tif->tif_data != 0); - if (DecoderState(tif)->dec_codetab) - _TIFFfree(DecoderState(tif)->dec_codetab); + if (DecoderState(tif)->dec_codetab) + _TIFFfree(DecoderState(tif)->dec_codetab); - if (EncoderState(tif)->enc_hashtab) - _TIFFfree(EncoderState(tif)->enc_hashtab); + if (EncoderState(tif)->enc_hashtab) + _TIFFfree(EncoderState(tif)->enc_hashtab); - _TIFFfree(tif->tif_data); - tif->tif_data = NULL; + _TIFFfree(tif->tif_data); + tif->tif_data = NULL; - _TIFFSetDefaultCompressionState(tif); + _TIFFSetDefaultCompressionState(tif); } int TIFFInitLZW(TIFF* tif, int scheme) { - static const char module[] = "TIFFInitLZW"; - assert(scheme == COMPRESSION_LZW); - /* - * Allocate state block so tag methods have storage to record values. - */ - tif->tif_data = (uint8*) _TIFFmalloc(sizeof (LZWCodecState)); - if (tif->tif_data == NULL) - goto bad; - DecoderState(tif)->dec_codetab = NULL; - DecoderState(tif)->dec_decode = NULL; - EncoderState(tif)->enc_hashtab = NULL; + static const char module[] = "TIFFInitLZW"; + assert(scheme == COMPRESSION_LZW); + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (uint8*) _TIFFmalloc(sizeof (LZWCodecState)); + if (tif->tif_data == NULL) + goto bad; + DecoderState(tif)->dec_codetab = NULL; + DecoderState(tif)->dec_decode = NULL; + EncoderState(tif)->enc_hashtab = NULL; LZWState(tif)->rw_mode = tif->tif_mode; - /* - * Install codec methods. - */ - tif->tif_fixuptags = LZWFixupTags; - tif->tif_setupdecode = LZWSetupDecode; - tif->tif_predecode = LZWPreDecode; - tif->tif_decoderow = LZWDecode; - tif->tif_decodestrip = LZWDecode; - tif->tif_decodetile = LZWDecode; - tif->tif_setupencode = LZWSetupEncode; - tif->tif_preencode = LZWPreEncode; - tif->tif_postencode = LZWPostEncode; - tif->tif_encoderow = LZWEncode; - tif->tif_encodestrip = LZWEncode; - tif->tif_encodetile = LZWEncode; - tif->tif_cleanup = LZWCleanup; - /* - * Setup predictor setup. - */ - (void) TIFFPredictorInit(tif); - return (1); + /* + * Install codec methods. + */ + tif->tif_fixuptags = LZWFixupTags; + tif->tif_setupdecode = LZWSetupDecode; + tif->tif_predecode = LZWPreDecode; + tif->tif_decoderow = LZWDecode; + tif->tif_decodestrip = LZWDecode; + tif->tif_decodetile = LZWDecode; + tif->tif_setupencode = LZWSetupEncode; + tif->tif_preencode = LZWPreEncode; + tif->tif_postencode = LZWPostEncode; + tif->tif_encoderow = LZWEncode; + tif->tif_encodestrip = LZWEncode; + tif->tif_encodetile = LZWEncode; + tif->tif_cleanup = LZWCleanup; + /* + * Setup predictor setup. + */ + (void) TIFFPredictorInit(tif); + return (1); bad: - TIFFErrorExt(tif->tif_clientdata, module, - "No space for LZW state block"); - return (0); + TIFFErrorExt(tif->tif_clientdata, module, + "No space for LZW state block"); + return (0); } /* diff --git a/3rdparty/libtiff/tif_next.c b/3rdparty/libtiff/tif_next.c index 6d324bcb1e..08211788ac 100644 --- a/3rdparty/libtiff/tif_next.c +++ b/3rdparty/libtiff/tif_next.c @@ -1,26 +1,26 @@ -/* $Id: tif_next.c,v 1.13 2010-03-10 18:56:48 bfriesen Exp $ */ +/* $Id: tif_next.c,v 1.19 2016-09-04 21:32:56 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -33,12 +33,12 @@ */ #define SETPIXEL(op, v) { \ - switch (npixels++ & 3) { \ - case 0: op[0] = (unsigned char) ((v) << 6); break; \ - case 1: op[0] |= (v) << 4; break; \ - case 2: op[0] |= (v) << 2; break; \ - case 3: *op++ |= (v); break; \ - } \ + switch (npixels++ & 3) { \ + case 0: op[0] = (unsigned char) ((v) << 6); break; \ + case 1: op[0] |= (v) << 4; break; \ + case 2: op[0] |= (v) << 2; break; \ + case 3: *op++ |= (v); op_offset++; break; \ + } \ } #define LITERALROW 0x00 @@ -48,105 +48,134 @@ static int NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) { - static const char module[] = "NeXTDecode"; - unsigned char *bp, *op; - tmsize_t cc; - uint8* row; - tmsize_t scanline, n; + static const char module[] = "NeXTDecode"; + unsigned char *bp, *op; + tmsize_t cc; + uint8* row; + tmsize_t scanline, n; - (void) s; - /* - * Each scanline is assumed to start off as all - * white (we assume a PhotometricInterpretation - * of ``min-is-black''). - */ - for (op = (unsigned char*) buf, cc = occ; cc-- > 0;) - *op++ = 0xff; + (void) s; + /* + * Each scanline is assumed to start off as all + * white (we assume a PhotometricInterpretation + * of ``min-is-black''). + */ + for (op = (unsigned char*) buf, cc = occ; cc-- > 0;) + *op++ = 0xff; - bp = (unsigned char *)tif->tif_rawcp; - cc = tif->tif_rawcc; - scanline = tif->tif_scanlinesize; - if (occ % scanline) - { - TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); - return (0); - } - for (row = buf; occ > 0; occ -= scanline, row += scanline) { - n = *bp++, cc--; - switch (n) { - case LITERALROW: - /* - * The entire scanline is given as literal values. - */ - if (cc < scanline) - goto bad; - _TIFFmemcpy(row, bp, scanline); - bp += scanline; - cc -= scanline; - break; - case LITERALSPAN: { - tmsize_t off; - /* - * The scanline has a literal span that begins at some - * offset. - */ - off = (bp[0] * 256) + bp[1]; - n = (bp[2] * 256) + bp[3]; - if (cc < 4+n || off+n > scanline) - goto bad; - _TIFFmemcpy(row+off, bp+4, n); - bp += 4+n; - cc -= 4+n; - break; - } - default: { - uint32 npixels = 0, grey; - uint32 imagewidth = tif->tif_dir.td_imagewidth; + bp = (unsigned char *)tif->tif_rawcp; + cc = tif->tif_rawcc; + scanline = tif->tif_scanlinesize; + if (occ % scanline) + { + TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); + return (0); + } + for (row = buf; cc > 0 && occ > 0; occ -= scanline, row += scanline) { + n = *bp++; + cc--; + switch (n) { + case LITERALROW: + /* + * The entire scanline is given as literal values. + */ + if (cc < scanline) + goto bad; + _TIFFmemcpy(row, bp, scanline); + bp += scanline; + cc -= scanline; + break; + case LITERALSPAN: { + tmsize_t off; + /* + * The scanline has a literal span that begins at some + * offset. + */ + if( cc < 4 ) + goto bad; + off = (bp[0] * 256) + bp[1]; + n = (bp[2] * 256) + bp[3]; + if (cc < 4+n || off+n > scanline) + goto bad; + _TIFFmemcpy(row+off, bp+4, n); + bp += 4+n; + cc -= 4+n; + break; + } + default: { + uint32 npixels = 0, grey; + tmsize_t op_offset = 0; + uint32 imagewidth = tif->tif_dir.td_imagewidth; + if( isTiled(tif) ) + imagewidth = tif->tif_dir.td_tilewidth; - /* - * The scanline is composed of a sequence of constant - * color ``runs''. We shift into ``run mode'' and - * interpret bytes as codes of the form - * until we've filled the scanline. - */ - op = row; - for (;;) { - grey = (uint32)((n>>6) & 0x3); - n &= 0x3f; - /* - * Ensure the run does not exceed the scanline - * bounds, potentially resulting in a security - * issue. - */ - while (n-- > 0 && npixels < imagewidth) - SETPIXEL(op, grey); - if (npixels >= imagewidth) - break; - if (cc == 0) - goto bad; - n = *bp++, cc--; - } - break; - } - } - } - tif->tif_rawcp = (uint8*) bp; - tif->tif_rawcc = cc; - return (1); + /* + * The scanline is composed of a sequence of constant + * color ``runs''. We shift into ``run mode'' and + * interpret bytes as codes of the form + * until we've filled the scanline. + */ + op = row; + for (;;) { + grey = (uint32)((n>>6) & 0x3); + n &= 0x3f; + /* + * Ensure the run does not exceed the scanline + * bounds, potentially resulting in a security + * issue. + */ + while (n-- > 0 && npixels < imagewidth && op_offset < scanline) + SETPIXEL(op, grey); + if (npixels >= imagewidth) + break; + if (op_offset >= scanline ) { + TIFFErrorExt(tif->tif_clientdata, module, "Invalid data for scanline %ld", + (long) tif->tif_row); + return (0); + } + if (cc == 0) + goto bad; + n = *bp++; + cc--; + } + break; + } + } + } + tif->tif_rawcp = (uint8*) bp; + tif->tif_rawcc = cc; + return (1); bad: - TIFFErrorExt(tif->tif_clientdata, module, "Not enough data for scanline %ld", - (long) tif->tif_row); - return (0); + TIFFErrorExt(tif->tif_clientdata, module, "Not enough data for scanline %ld", + (long) tif->tif_row); + return (0); } +static int +NeXTPreDecode(TIFF* tif, uint16 s) +{ + static const char module[] = "NeXTPreDecode"; + TIFFDirectory *td = &tif->tif_dir; + (void)s; + + if( td->td_bitspersample != 2 ) + { + TIFFErrorExt(tif->tif_clientdata, module, "Unsupported BitsPerSample = %d", + td->td_bitspersample); + return (0); + } + return (1); +} + int TIFFInitNeXT(TIFF* tif, int scheme) { - (void) scheme; - tif->tif_decoderow = NeXTDecode; - tif->tif_decodestrip = NeXTDecode; - tif->tif_decodetile = NeXTDecode; - return (1); + (void) scheme; + tif->tif_predecode = NeXTPreDecode; + tif->tif_decoderow = NeXTDecode; + tif->tif_decodestrip = NeXTDecode; + tif->tif_decodetile = NeXTDecode; + return (1); } #endif /* NEXT_SUPPORT */ diff --git a/3rdparty/libtiff/tif_ojpeg.c b/3rdparty/libtiff/tif_ojpeg.c index 43055cd63b..92ed1fa19e 100644 --- a/3rdparty/libtiff/tif_ojpeg.c +++ b/3rdparty/libtiff/tif_ojpeg.c @@ -1,4 +1,4 @@ -/* $Id: tif_ojpeg.c,v 1.56 2012-05-24 03:15:18 fwarmerdam Exp $ */ +/* $Id: tif_ojpeg.c,v 1.69 2017-04-27 17:29:26 erouault Exp $ */ /* WARNING: The type of JPEG encapsulation defined by the TIFF Version 6.0 specification is now totally obsolete and deprecated for new applications and @@ -39,7 +39,7 @@ OF THIS SOFTWARE. Joris Van Damme and/or AWare Systems may be available for custom - developement. If you like what you see, and need anything similar or related, + development. If you like what you see, and need anything similar or related, contact . */ @@ -75,7 +75,7 @@ OJPEGSubsamplingCorrect, making no note of any other data, reporting no warnings or errors, up to the point where either these values are read, or it's clear they aren't there. This means that some of the data is read twice, but we feel speed - in correcting these values is important enough to warrant this sacrifice. Allthough + in correcting these values is important enough to warrant this sacrifice. Although there is currently no define or other configuration mechanism to disable this behaviour, the actual header scanning is build to robustly respond with error report if it should encounter an uncorrected mismatch of subsampling values. See @@ -84,7 +84,7 @@ The restart interval and restart markers are the most tricky part... The restart interval can be specified in a tag. It can also be set inside the input JPEG stream. It can be used inside the input JPEG stream. If reading from strile data, we've - consistenly discovered the need to insert restart markers in between the different + consistently discovered the need to insert restart markers in between the different striles, as is also probably the most likely interpretation of the original TIFF 6.0 specification. With all this setting of interval, and actual use of markers that is not predictable at the time of valid JPEG header assembly, the restart thing may turn @@ -113,7 +113,7 @@ planarconfig is not separate (vast majority). We may one day use that to build converters to JPEG, and/or to new-style JPEG compression inside TIFF. - A dissadvantage is the lack of random access to the individual striles. This is the + A disadvantage is the lack of random access to the individual striles. This is the reason for much of the complicated restart-and-position stuff inside OJPEGPreDecode. Applications would do well accessing all striles in order, as this will result in a single sequential scan of the input stream, and no restarting of LibJpeg decoding @@ -135,13 +135,13 @@ * The default mode, without JPEG_ENCAP_EXTERNAL, implements the call encapsulators * here, internally, with normal longjump. * SETJMP, LONGJMP, JMP_BUF: On some machines/environments a longjump equivalent is - * conviniently available, but still it may be worthwhile to use _setjmp or sigsetjmp + * conveniently available, but still it may be worthwhile to use _setjmp or sigsetjmp * in place of plain setjmp. These macros will make it easier. It is useless * to fiddle with these if you define JPEG_ENCAP_EXTERNAL. * OJPEG_BUFFER: Define the size of the desired buffer here. Should be small enough so as to guarantee * instant processing, optimal streaming and optimal use of processor cache, but also big * enough so as to not result in significant call overhead. It should be at least a few - * bytes to accomodate some structures (this is verified in asserts), but it would not be + * bytes to accommodate some structures (this is verified in asserts), but it would not be * sensible to make it this small anyway, and it should be at most 64K since it is indexed * with uint16. We recommend 2K. * EGYPTIANWALK: You could also define EGYPTIANWALK here, but it is not used anywhere and has @@ -177,13 +177,13 @@ #define FIELD_OJPEG_JPEGRESTARTINTERVAL (FIELD_CODEC+6) static const TIFFField ojpegFields[] = { - {TIFFTAG_JPEGIFOFFSET,1,1,TIFF_LONG8,0,TIFF_SETGET_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGINTERCHANGEFORMAT,TRUE,FALSE,"JpegInterchangeFormat",NULL}, - {TIFFTAG_JPEGIFBYTECOUNT,1,1,TIFF_LONG8,0,TIFF_SETGET_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH,TRUE,FALSE,"JpegInterchangeFormatLength",NULL}, - {TIFFTAG_JPEGQTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGQTABLES,FALSE,TRUE,"JpegQTables",NULL}, - {TIFFTAG_JPEGDCTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGDCTABLES,FALSE,TRUE,"JpegDcTables",NULL}, - {TIFFTAG_JPEGACTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGACTABLES,FALSE,TRUE,"JpegAcTables",NULL}, - {TIFFTAG_JPEGPROC,1,1,TIFF_SHORT,0,TIFF_SETGET_UINT16,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGPROC,FALSE,FALSE,"JpegProc",NULL}, - {TIFFTAG_JPEGRESTARTINTERVAL,1,1,TIFF_SHORT,0,TIFF_SETGET_UINT16,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGRESTARTINTERVAL,FALSE,FALSE,"JpegRestartInterval",NULL}, + {TIFFTAG_JPEGIFOFFSET,1,1,TIFF_LONG8,0,TIFF_SETGET_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGINTERCHANGEFORMAT,TRUE,FALSE,"JpegInterchangeFormat",NULL}, + {TIFFTAG_JPEGIFBYTECOUNT,1,1,TIFF_LONG8,0,TIFF_SETGET_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH,TRUE,FALSE,"JpegInterchangeFormatLength",NULL}, + {TIFFTAG_JPEGQTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGQTABLES,FALSE,TRUE,"JpegQTables",NULL}, + {TIFFTAG_JPEGDCTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGDCTABLES,FALSE,TRUE,"JpegDcTables",NULL}, + {TIFFTAG_JPEGACTABLES,TIFF_VARIABLE2,TIFF_VARIABLE2,TIFF_LONG8,0,TIFF_SETGET_C32_UINT64,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGACTABLES,FALSE,TRUE,"JpegAcTables",NULL}, + {TIFFTAG_JPEGPROC,1,1,TIFF_SHORT,0,TIFF_SETGET_UINT16,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGPROC,FALSE,FALSE,"JpegProc",NULL}, + {TIFFTAG_JPEGRESTARTINTERVAL,1,1,TIFF_SHORT,0,TIFF_SETGET_UINT16,TIFF_SETGET_UNDEFINED,FIELD_OJPEG_JPEGRESTARTINTERVAL,FALSE,FALSE,"JpegRestartInterval",NULL}, }; #ifndef LIBJPEG_ENCAP_EXTERNAL @@ -200,7 +200,7 @@ static const TIFFField ojpegFields[] = { Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is not defined. Unfortunately, the MinGW and Borland compilers include a typedef for INT32, which causes a conflict. MSVC does not include - a conficting typedef given the headers which are included. + a conflicting typedef given the headers which are included. */ #if defined(__BORLANDC__) || defined(__MINGW32__) # define XMD_H 1 @@ -223,117 +223,118 @@ typedef struct jpeg_decompress_struct jpeg_decompress_struct; typedef struct jpeg_source_mgr jpeg_source_mgr; typedef enum { - osibsNotSetYet, - osibsJpegInterchangeFormat, - osibsStrile, - osibsEof + osibsNotSetYet, + osibsJpegInterchangeFormat, + osibsStrile, + osibsEof } OJPEGStateInBufferSource; typedef enum { - ososSoi, - ososQTable0,ososQTable1,ososQTable2,ososQTable3, - ososDcTable0,ososDcTable1,ososDcTable2,ososDcTable3, - ososAcTable0,ososAcTable1,ososAcTable2,ososAcTable3, - ososDri, - ososSof, - ososSos, - ososCompressed, - ososRst, - ososEoi + ososSoi, + ososQTable0,ososQTable1,ososQTable2,ososQTable3, + ososDcTable0,ososDcTable1,ososDcTable2,ososDcTable3, + ososAcTable0,ososAcTable1,ososAcTable2,ososAcTable3, + ososDri, + ososSof, + ososSos, + ososCompressed, + ososRst, + ososEoi } OJPEGStateOutState; typedef struct { - TIFF* tif; - #ifndef LIBJPEG_ENCAP_EXTERNAL - JMP_BUF exit_jmpbuf; - #endif - TIFFVGetMethod vgetparent; - TIFFVSetMethod vsetparent; - TIFFPrintMethod printdir; - uint64 file_size; - uint32 image_width; - uint32 image_length; - uint32 strile_width; - uint32 strile_length; - uint32 strile_length_total; - uint8 samples_per_pixel; - uint8 plane_sample_offset; - uint8 samples_per_pixel_per_plane; - uint64 jpeg_interchange_format; - uint64 jpeg_interchange_format_length; - uint8 jpeg_proc; - uint8 subsamplingcorrect; - uint8 subsamplingcorrect_done; - uint8 subsampling_tag; - uint8 subsampling_hor; - uint8 subsampling_ver; - uint8 subsampling_force_desubsampling_inside_decompression; - uint8 qtable_offset_count; - uint8 dctable_offset_count; - uint8 actable_offset_count; - uint64 qtable_offset[3]; - uint64 dctable_offset[3]; - uint64 actable_offset[3]; - uint8* qtable[4]; - uint8* dctable[4]; - uint8* actable[4]; - uint16 restart_interval; - uint8 restart_index; - uint8 sof_log; - uint8 sof_marker_id; - uint32 sof_x; - uint32 sof_y; - uint8 sof_c[3]; - uint8 sof_hv[3]; - uint8 sof_tq[3]; - uint8 sos_cs[3]; - uint8 sos_tda[3]; - struct { - uint8 log; - OJPEGStateInBufferSource in_buffer_source; - uint32 in_buffer_next_strile; - uint64 in_buffer_file_pos; - uint64 in_buffer_file_togo; - } sos_end[3]; - uint8 readheader_done; - uint8 writeheader_done; - uint16 write_cursample; - uint32 write_curstrile; - uint8 libjpeg_session_active; - uint8 libjpeg_jpeg_query_style; - jpeg_error_mgr libjpeg_jpeg_error_mgr; - jpeg_decompress_struct libjpeg_jpeg_decompress_struct; - jpeg_source_mgr libjpeg_jpeg_source_mgr; - uint8 subsampling_convert_log; - uint32 subsampling_convert_ylinelen; - uint32 subsampling_convert_ylines; - uint32 subsampling_convert_clinelen; - uint32 subsampling_convert_clines; - uint32 subsampling_convert_ybuflen; - uint32 subsampling_convert_cbuflen; - uint32 subsampling_convert_ycbcrbuflen; - uint8* subsampling_convert_ycbcrbuf; - uint8* subsampling_convert_ybuf; - uint8* subsampling_convert_cbbuf; - uint8* subsampling_convert_crbuf; - uint32 subsampling_convert_ycbcrimagelen; - uint8** subsampling_convert_ycbcrimage; - uint32 subsampling_convert_clinelenout; - uint32 subsampling_convert_state; - uint32 bytes_per_line; /* if the codec outputs subsampled data, a 'line' in bytes_per_line */ - uint32 lines_per_strile; /* and lines_per_strile means subsampling_ver desubsampled rows */ - OJPEGStateInBufferSource in_buffer_source; - uint32 in_buffer_next_strile; - uint32 in_buffer_strile_count; - uint64 in_buffer_file_pos; - uint8 in_buffer_file_pos_log; - uint64 in_buffer_file_togo; - uint16 in_buffer_togo; - uint8* in_buffer_cur; - uint8 in_buffer[OJPEG_BUFFER]; - OJPEGStateOutState out_state; - uint8 out_buffer[OJPEG_BUFFER]; - uint8* skip_buffer; + TIFF* tif; + int decoder_ok; + #ifndef LIBJPEG_ENCAP_EXTERNAL + JMP_BUF exit_jmpbuf; + #endif + TIFFVGetMethod vgetparent; + TIFFVSetMethod vsetparent; + TIFFPrintMethod printdir; + uint64 file_size; + uint32 image_width; + uint32 image_length; + uint32 strile_width; + uint32 strile_length; + uint32 strile_length_total; + uint8 samples_per_pixel; + uint8 plane_sample_offset; + uint8 samples_per_pixel_per_plane; + uint64 jpeg_interchange_format; + uint64 jpeg_interchange_format_length; + uint8 jpeg_proc; + uint8 subsamplingcorrect; + uint8 subsamplingcorrect_done; + uint8 subsampling_tag; + uint8 subsampling_hor; + uint8 subsampling_ver; + uint8 subsampling_force_desubsampling_inside_decompression; + uint8 qtable_offset_count; + uint8 dctable_offset_count; + uint8 actable_offset_count; + uint64 qtable_offset[3]; + uint64 dctable_offset[3]; + uint64 actable_offset[3]; + uint8* qtable[4]; + uint8* dctable[4]; + uint8* actable[4]; + uint16 restart_interval; + uint8 restart_index; + uint8 sof_log; + uint8 sof_marker_id; + uint32 sof_x; + uint32 sof_y; + uint8 sof_c[3]; + uint8 sof_hv[3]; + uint8 sof_tq[3]; + uint8 sos_cs[3]; + uint8 sos_tda[3]; + struct { + uint8 log; + OJPEGStateInBufferSource in_buffer_source; + uint32 in_buffer_next_strile; + uint64 in_buffer_file_pos; + uint64 in_buffer_file_togo; + } sos_end[3]; + uint8 readheader_done; + uint8 writeheader_done; + uint16 write_cursample; + uint32 write_curstrile; + uint8 libjpeg_session_active; + uint8 libjpeg_jpeg_query_style; + jpeg_error_mgr libjpeg_jpeg_error_mgr; + jpeg_decompress_struct libjpeg_jpeg_decompress_struct; + jpeg_source_mgr libjpeg_jpeg_source_mgr; + uint8 subsampling_convert_log; + uint32 subsampling_convert_ylinelen; + uint32 subsampling_convert_ylines; + uint32 subsampling_convert_clinelen; + uint32 subsampling_convert_clines; + uint32 subsampling_convert_ybuflen; + uint32 subsampling_convert_cbuflen; + uint32 subsampling_convert_ycbcrbuflen; + uint8* subsampling_convert_ycbcrbuf; + uint8* subsampling_convert_ybuf; + uint8* subsampling_convert_cbbuf; + uint8* subsampling_convert_crbuf; + uint32 subsampling_convert_ycbcrimagelen; + uint8** subsampling_convert_ycbcrimage; + uint32 subsampling_convert_clinelenout; + uint32 subsampling_convert_state; + uint32 bytes_per_line; /* if the codec outputs subsampled data, a 'line' in bytes_per_line */ + uint32 lines_per_strile; /* and lines_per_strile means subsampling_ver desubsampled rows */ + OJPEGStateInBufferSource in_buffer_source; + uint32 in_buffer_next_strile; + uint32 in_buffer_strile_count; + uint64 in_buffer_file_pos; + uint8 in_buffer_file_pos_log; + uint64 in_buffer_file_togo; + uint16 in_buffer_togo; + uint8* in_buffer_cur; + uint8 in_buffer[OJPEG_BUFFER]; + OJPEGStateOutState out_state; + uint8 out_buffer[OJPEG_BUFFER]; + uint8* skip_buffer; } OJPEGState; static int OJPEGVGetField(TIFF* tif, uint32 tag, va_list ap); @@ -418,1963 +419,2002 @@ static void OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo); int TIFFInitOJPEG(TIFF* tif, int scheme) { - static const char module[]="TIFFInitOJPEG"; - OJPEGState* sp; + static const char module[]="TIFFInitOJPEG"; + OJPEGState* sp; - assert(scheme==COMPRESSION_OJPEG); + assert(scheme==COMPRESSION_OJPEG); /* - * Merge codec-specific tag information. - */ - if (!_TIFFMergeFields(tif, ojpegFields, TIFFArrayCount(ojpegFields))) { - TIFFErrorExt(tif->tif_clientdata, module, - "Merging Old JPEG codec-specific tags failed"); - return 0; - } + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, ojpegFields, TIFFArrayCount(ojpegFields))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Merging Old JPEG codec-specific tags failed"); + return 0; + } - /* state block */ - sp=_TIFFmalloc(sizeof(OJPEGState)); - if (sp==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"No space for OJPEG state block"); - return(0); - } - _TIFFmemset(sp,0,sizeof(OJPEGState)); - sp->tif=tif; - sp->jpeg_proc=1; - sp->subsampling_hor=2; - sp->subsampling_ver=2; - TIFFSetField(tif,TIFFTAG_YCBCRSUBSAMPLING,2,2); - /* tif codec methods */ - tif->tif_fixuptags=OJPEGFixupTags; - tif->tif_setupdecode=OJPEGSetupDecode; - tif->tif_predecode=OJPEGPreDecode; - tif->tif_postdecode=OJPEGPostDecode; - tif->tif_decoderow=OJPEGDecode; - tif->tif_decodestrip=OJPEGDecode; - tif->tif_decodetile=OJPEGDecode; - tif->tif_setupencode=OJPEGSetupEncode; - tif->tif_preencode=OJPEGPreEncode; - tif->tif_postencode=OJPEGPostEncode; - tif->tif_encoderow=OJPEGEncode; - tif->tif_encodestrip=OJPEGEncode; - tif->tif_encodetile=OJPEGEncode; - tif->tif_cleanup=OJPEGCleanup; - tif->tif_data=(uint8*)sp; - /* tif tag methods */ - sp->vgetparent=tif->tif_tagmethods.vgetfield; - tif->tif_tagmethods.vgetfield=OJPEGVGetField; - sp->vsetparent=tif->tif_tagmethods.vsetfield; - tif->tif_tagmethods.vsetfield=OJPEGVSetField; - sp->printdir=tif->tif_tagmethods.printdir; - tif->tif_tagmethods.printdir=OJPEGPrintDir; - /* Some OJPEG files don't have strip or tile offsets or bytecounts tags. - Some others do, but have totally meaningless or corrupt values - in these tags. In these cases, the JpegInterchangeFormat stream is - reliable. In any case, this decoder reads the compressed data itself, - from the most reliable locations, and we need to notify encapsulating - LibTiff not to read raw strips or tiles for us. */ - tif->tif_flags|=TIFF_NOREADRAW; - return(1); + /* state block */ + sp=_TIFFmalloc(sizeof(OJPEGState)); + if (sp==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"No space for OJPEG state block"); + return(0); + } + _TIFFmemset(sp,0,sizeof(OJPEGState)); + sp->tif=tif; + sp->jpeg_proc=1; + sp->subsampling_hor=2; + sp->subsampling_ver=2; + TIFFSetField(tif,TIFFTAG_YCBCRSUBSAMPLING,2,2); + /* tif codec methods */ + tif->tif_fixuptags=OJPEGFixupTags; + tif->tif_setupdecode=OJPEGSetupDecode; + tif->tif_predecode=OJPEGPreDecode; + tif->tif_postdecode=OJPEGPostDecode; + tif->tif_decoderow=OJPEGDecode; + tif->tif_decodestrip=OJPEGDecode; + tif->tif_decodetile=OJPEGDecode; + tif->tif_setupencode=OJPEGSetupEncode; + tif->tif_preencode=OJPEGPreEncode; + tif->tif_postencode=OJPEGPostEncode; + tif->tif_encoderow=OJPEGEncode; + tif->tif_encodestrip=OJPEGEncode; + tif->tif_encodetile=OJPEGEncode; + tif->tif_cleanup=OJPEGCleanup; + tif->tif_data=(uint8*)sp; + /* tif tag methods */ + sp->vgetparent=tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield=OJPEGVGetField; + sp->vsetparent=tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield=OJPEGVSetField; + sp->printdir=tif->tif_tagmethods.printdir; + tif->tif_tagmethods.printdir=OJPEGPrintDir; + /* Some OJPEG files don't have strip or tile offsets or bytecounts tags. + Some others do, but have totally meaningless or corrupt values + in these tags. In these cases, the JpegInterchangeFormat stream is + reliable. In any case, this decoder reads the compressed data itself, + from the most reliable locations, and we need to notify encapsulating + LibTiff not to read raw strips or tiles for us. */ + tif->tif_flags|=TIFF_NOREADRAW; + return(1); } static int OJPEGVGetField(TIFF* tif, uint32 tag, va_list ap) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - switch(tag) - { - case TIFFTAG_JPEGIFOFFSET: - *va_arg(ap,uint64*)=(uint64)sp->jpeg_interchange_format; - break; - case TIFFTAG_JPEGIFBYTECOUNT: - *va_arg(ap,uint64*)=(uint64)sp->jpeg_interchange_format_length; - break; - case TIFFTAG_YCBCRSUBSAMPLING: - if (sp->subsamplingcorrect_done==0) - OJPEGSubsamplingCorrect(tif); - *va_arg(ap,uint16*)=(uint16)sp->subsampling_hor; - *va_arg(ap,uint16*)=(uint16)sp->subsampling_ver; - break; - case TIFFTAG_JPEGQTABLES: - *va_arg(ap,uint32*)=(uint32)sp->qtable_offset_count; - *va_arg(ap,void**)=(void*)sp->qtable_offset; - break; - case TIFFTAG_JPEGDCTABLES: - *va_arg(ap,uint32*)=(uint32)sp->dctable_offset_count; - *va_arg(ap,void**)=(void*)sp->dctable_offset; - break; - case TIFFTAG_JPEGACTABLES: - *va_arg(ap,uint32*)=(uint32)sp->actable_offset_count; - *va_arg(ap,void**)=(void*)sp->actable_offset; - break; - case TIFFTAG_JPEGPROC: - *va_arg(ap,uint16*)=(uint16)sp->jpeg_proc; - break; - case TIFFTAG_JPEGRESTARTINTERVAL: - *va_arg(ap,uint16*)=sp->restart_interval; - break; - default: - return (*sp->vgetparent)(tif,tag,ap); - } - return (1); + OJPEGState* sp=(OJPEGState*)tif->tif_data; + switch(tag) + { + case TIFFTAG_JPEGIFOFFSET: + *va_arg(ap,uint64*)=(uint64)sp->jpeg_interchange_format; + break; + case TIFFTAG_JPEGIFBYTECOUNT: + *va_arg(ap,uint64*)=(uint64)sp->jpeg_interchange_format_length; + break; + case TIFFTAG_YCBCRSUBSAMPLING: + if (sp->subsamplingcorrect_done==0) + OJPEGSubsamplingCorrect(tif); + *va_arg(ap,uint16*)=(uint16)sp->subsampling_hor; + *va_arg(ap,uint16*)=(uint16)sp->subsampling_ver; + break; + case TIFFTAG_JPEGQTABLES: + *va_arg(ap,uint32*)=(uint32)sp->qtable_offset_count; + *va_arg(ap,void**)=(void*)sp->qtable_offset; + break; + case TIFFTAG_JPEGDCTABLES: + *va_arg(ap,uint32*)=(uint32)sp->dctable_offset_count; + *va_arg(ap,void**)=(void*)sp->dctable_offset; + break; + case TIFFTAG_JPEGACTABLES: + *va_arg(ap,uint32*)=(uint32)sp->actable_offset_count; + *va_arg(ap,void**)=(void*)sp->actable_offset; + break; + case TIFFTAG_JPEGPROC: + *va_arg(ap,uint16*)=(uint16)sp->jpeg_proc; + break; + case TIFFTAG_JPEGRESTARTINTERVAL: + *va_arg(ap,uint16*)=sp->restart_interval; + break; + default: + return (*sp->vgetparent)(tif,tag,ap); + } + return (1); } static int OJPEGVSetField(TIFF* tif, uint32 tag, va_list ap) { - static const char module[]="OJPEGVSetField"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint32 ma; - uint64* mb; - uint32 n; - switch(tag) - { - case TIFFTAG_JPEGIFOFFSET: - sp->jpeg_interchange_format=(uint64)va_arg(ap,uint64); - break; - case TIFFTAG_JPEGIFBYTECOUNT: - sp->jpeg_interchange_format_length=(uint64)va_arg(ap,uint64); - break; - case TIFFTAG_YCBCRSUBSAMPLING: - sp->subsampling_tag=1; - sp->subsampling_hor=(uint8)va_arg(ap,uint16_vap); - sp->subsampling_ver=(uint8)va_arg(ap,uint16_vap); - tif->tif_dir.td_ycbcrsubsampling[0]=sp->subsampling_hor; - tif->tif_dir.td_ycbcrsubsampling[1]=sp->subsampling_ver; - break; - case TIFFTAG_JPEGQTABLES: - ma=(uint32)va_arg(ap,uint32); - if (ma!=0) - { - if (ma>3) - { - TIFFErrorExt(tif->tif_clientdata,module,"JpegQTables tag has incorrect count"); - return(0); - } - sp->qtable_offset_count=(uint8)ma; - mb=(uint64*)va_arg(ap,uint64*); - for (n=0; nqtable_offset[n]=mb[n]; - } - break; - case TIFFTAG_JPEGDCTABLES: - ma=(uint32)va_arg(ap,uint32); - if (ma!=0) - { - if (ma>3) - { - TIFFErrorExt(tif->tif_clientdata,module,"JpegDcTables tag has incorrect count"); - return(0); - } - sp->dctable_offset_count=(uint8)ma; - mb=(uint64*)va_arg(ap,uint64*); - for (n=0; ndctable_offset[n]=mb[n]; - } - break; - case TIFFTAG_JPEGACTABLES: - ma=(uint32)va_arg(ap,uint32); - if (ma!=0) - { - if (ma>3) - { - TIFFErrorExt(tif->tif_clientdata,module,"JpegAcTables tag has incorrect count"); - return(0); - } - sp->actable_offset_count=(uint8)ma; - mb=(uint64*)va_arg(ap,uint64*); - for (n=0; nactable_offset[n]=mb[n]; - } - break; - case TIFFTAG_JPEGPROC: - sp->jpeg_proc=(uint8)va_arg(ap,uint16_vap); - break; - case TIFFTAG_JPEGRESTARTINTERVAL: - sp->restart_interval=(uint16)va_arg(ap,uint16_vap); - break; - default: - return (*sp->vsetparent)(tif,tag,ap); - } - TIFFSetFieldBit(tif,TIFFFieldWithTag(tif,tag)->field_bit); - tif->tif_flags|=TIFF_DIRTYDIRECT; - return(1); + static const char module[]="OJPEGVSetField"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint32 ma; + uint64* mb; + uint32 n; + const TIFFField* fip; + + switch(tag) + { + case TIFFTAG_JPEGIFOFFSET: + sp->jpeg_interchange_format=(uint64)va_arg(ap,uint64); + break; + case TIFFTAG_JPEGIFBYTECOUNT: + sp->jpeg_interchange_format_length=(uint64)va_arg(ap,uint64); + break; + case TIFFTAG_YCBCRSUBSAMPLING: + sp->subsampling_tag=1; + sp->subsampling_hor=(uint8)va_arg(ap,uint16_vap); + sp->subsampling_ver=(uint8)va_arg(ap,uint16_vap); + tif->tif_dir.td_ycbcrsubsampling[0]=sp->subsampling_hor; + tif->tif_dir.td_ycbcrsubsampling[1]=sp->subsampling_ver; + break; + case TIFFTAG_JPEGQTABLES: + ma=(uint32)va_arg(ap,uint32); + if (ma!=0) + { + if (ma>3) + { + TIFFErrorExt(tif->tif_clientdata,module,"JpegQTables tag has incorrect count"); + return(0); + } + sp->qtable_offset_count=(uint8)ma; + mb=(uint64*)va_arg(ap,uint64*); + for (n=0; nqtable_offset[n]=mb[n]; + } + break; + case TIFFTAG_JPEGDCTABLES: + ma=(uint32)va_arg(ap,uint32); + if (ma!=0) + { + if (ma>3) + { + TIFFErrorExt(tif->tif_clientdata,module,"JpegDcTables tag has incorrect count"); + return(0); + } + sp->dctable_offset_count=(uint8)ma; + mb=(uint64*)va_arg(ap,uint64*); + for (n=0; ndctable_offset[n]=mb[n]; + } + break; + case TIFFTAG_JPEGACTABLES: + ma=(uint32)va_arg(ap,uint32); + if (ma!=0) + { + if (ma>3) + { + TIFFErrorExt(tif->tif_clientdata,module,"JpegAcTables tag has incorrect count"); + return(0); + } + sp->actable_offset_count=(uint8)ma; + mb=(uint64*)va_arg(ap,uint64*); + for (n=0; nactable_offset[n]=mb[n]; + } + break; + case TIFFTAG_JPEGPROC: + sp->jpeg_proc=(uint8)va_arg(ap,uint16_vap); + break; + case TIFFTAG_JPEGRESTARTINTERVAL: + sp->restart_interval=(uint16)va_arg(ap,uint16_vap); + break; + default: + return (*sp->vsetparent)(tif,tag,ap); + } + fip = TIFFFieldWithTag(tif,tag); + if( fip == NULL ) /* shouldn't happen */ + return(0); + TIFFSetFieldBit(tif,fip->field_bit); + tif->tif_flags|=TIFF_DIRTYDIRECT; + return(1); } static void OJPEGPrintDir(TIFF* tif, FILE* fd, long flags) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8 m; - (void)flags; - assert(sp!=NULL); - if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMAT)) - fprintf(fd," JpegInterchangeFormat: " TIFF_UINT64_FORMAT "\n",(TIFF_UINT64_T)sp->jpeg_interchange_format); - if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH)) - fprintf(fd," JpegInterchangeFormatLength: " TIFF_UINT64_FORMAT "\n",(TIFF_UINT64_T)sp->jpeg_interchange_format_length); - if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGQTABLES)) - { - fprintf(fd," JpegQTables:"); - for (m=0; mqtable_offset_count; m++) - fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->qtable_offset[m]); - fprintf(fd,"\n"); - } - if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGDCTABLES)) - { - fprintf(fd," JpegDcTables:"); - for (m=0; mdctable_offset_count; m++) - fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->dctable_offset[m]); - fprintf(fd,"\n"); - } - if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGACTABLES)) - { - fprintf(fd," JpegAcTables:"); - for (m=0; mactable_offset_count; m++) - fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->actable_offset[m]); - fprintf(fd,"\n"); - } - if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGPROC)) - fprintf(fd," JpegProc: %u\n",(unsigned int)sp->jpeg_proc); - if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGRESTARTINTERVAL)) - fprintf(fd," JpegRestartInterval: %u\n",(unsigned int)sp->restart_interval); - if (sp->printdir) - (*sp->printdir)(tif, fd, flags); + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + (void)flags; + assert(sp!=NULL); + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMAT)) + fprintf(fd," JpegInterchangeFormat: " TIFF_UINT64_FORMAT "\n",(TIFF_UINT64_T)sp->jpeg_interchange_format); + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH)) + fprintf(fd," JpegInterchangeFormatLength: " TIFF_UINT64_FORMAT "\n",(TIFF_UINT64_T)sp->jpeg_interchange_format_length); + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGQTABLES)) + { + fprintf(fd," JpegQTables:"); + for (m=0; mqtable_offset_count; m++) + fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->qtable_offset[m]); + fprintf(fd,"\n"); + } + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGDCTABLES)) + { + fprintf(fd," JpegDcTables:"); + for (m=0; mdctable_offset_count; m++) + fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->dctable_offset[m]); + fprintf(fd,"\n"); + } + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGACTABLES)) + { + fprintf(fd," JpegAcTables:"); + for (m=0; mactable_offset_count; m++) + fprintf(fd," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->actable_offset[m]); + fprintf(fd,"\n"); + } + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGPROC)) + fprintf(fd," JpegProc: %u\n",(unsigned int)sp->jpeg_proc); + if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGRESTARTINTERVAL)) + fprintf(fd," JpegRestartInterval: %u\n",(unsigned int)sp->restart_interval); + if (sp->printdir) + (*sp->printdir)(tif, fd, flags); } static int OJPEGFixupTags(TIFF* tif) { - (void) tif; - return(1); + (void) tif; + return(1); } static int OJPEGSetupDecode(TIFF* tif) { - static const char module[]="OJPEGSetupDecode"; - TIFFWarningExt(tif->tif_clientdata,module,"Depreciated and troublesome old-style JPEG compression mode, please convert to new-style JPEG compression and notify vendor of writing software"); - return(1); + static const char module[]="OJPEGSetupDecode"; + TIFFWarningExt(tif->tif_clientdata,module,"Depreciated and troublesome old-style JPEG compression mode, please convert to new-style JPEG compression and notify vendor of writing software"); + return(1); } static int OJPEGPreDecode(TIFF* tif, uint16 s) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint32 m; - if (sp->subsamplingcorrect_done==0) - OJPEGSubsamplingCorrect(tif); - if (sp->readheader_done==0) - { - if (OJPEGReadHeaderInfo(tif)==0) - return(0); - } - if (sp->sos_end[s].log==0) - { - if (OJPEGReadSecondarySos(tif,s)==0) - return(0); - } - if isTiled(tif) - m=tif->tif_curtile; - else - m=tif->tif_curstrip; - if ((sp->writeheader_done!=0) && ((sp->write_cursample!=s) || (sp->write_curstrile>m))) - { - if (sp->libjpeg_session_active!=0) - OJPEGLibjpegSessionAbort(tif); - sp->writeheader_done=0; - } - if (sp->writeheader_done==0) - { - sp->plane_sample_offset=(uint8)s; - sp->write_cursample=s; - sp->write_curstrile=s*tif->tif_dir.td_stripsperimage; - if ((sp->in_buffer_file_pos_log==0) || - (sp->in_buffer_file_pos-sp->in_buffer_togo!=sp->sos_end[s].in_buffer_file_pos)) - { - sp->in_buffer_source=sp->sos_end[s].in_buffer_source; - sp->in_buffer_next_strile=sp->sos_end[s].in_buffer_next_strile; - sp->in_buffer_file_pos=sp->sos_end[s].in_buffer_file_pos; - sp->in_buffer_file_pos_log=0; - sp->in_buffer_file_togo=sp->sos_end[s].in_buffer_file_togo; - sp->in_buffer_togo=0; - sp->in_buffer_cur=0; - } - if (OJPEGWriteHeaderInfo(tif)==0) - return(0); - } - while (sp->write_curstrilelibjpeg_jpeg_query_style==0) - { - if (OJPEGPreDecodeSkipRaw(tif)==0) - return(0); - } - else - { - if (OJPEGPreDecodeSkipScanlines(tif)==0) - return(0); - } - sp->write_curstrile++; - } - return(1); + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint32 m; + if (sp->subsamplingcorrect_done==0) + OJPEGSubsamplingCorrect(tif); + if (sp->readheader_done==0) + { + if (OJPEGReadHeaderInfo(tif)==0) + return(0); + } + if (sp->sos_end[s].log==0) + { + if (OJPEGReadSecondarySos(tif,s)==0) + return(0); + } + if isTiled(tif) + m=tif->tif_curtile; + else + m=tif->tif_curstrip; + if ((sp->writeheader_done!=0) && ((sp->write_cursample!=s) || (sp->write_curstrile>m))) + { + if (sp->libjpeg_session_active!=0) + OJPEGLibjpegSessionAbort(tif); + sp->writeheader_done=0; + } + if (sp->writeheader_done==0) + { + sp->plane_sample_offset=(uint8)s; + sp->write_cursample=s; + sp->write_curstrile=s*tif->tif_dir.td_stripsperimage; + if ((sp->in_buffer_file_pos_log==0) || + (sp->in_buffer_file_pos-sp->in_buffer_togo!=sp->sos_end[s].in_buffer_file_pos)) + { + sp->in_buffer_source=sp->sos_end[s].in_buffer_source; + sp->in_buffer_next_strile=sp->sos_end[s].in_buffer_next_strile; + sp->in_buffer_file_pos=sp->sos_end[s].in_buffer_file_pos; + sp->in_buffer_file_pos_log=0; + sp->in_buffer_file_togo=sp->sos_end[s].in_buffer_file_togo; + sp->in_buffer_togo=0; + sp->in_buffer_cur=0; + } + if (OJPEGWriteHeaderInfo(tif)==0) + return(0); + } + while (sp->write_curstrilelibjpeg_jpeg_query_style==0) + { + if (OJPEGPreDecodeSkipRaw(tif)==0) + return(0); + } + else + { + if (OJPEGPreDecodeSkipScanlines(tif)==0) + return(0); + } + sp->write_curstrile++; + } + sp->decoder_ok = 1; + return(1); } static int OJPEGPreDecodeSkipRaw(TIFF* tif) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint32 m; - m=sp->lines_per_strile; - if (sp->subsampling_convert_state!=0) - { - if (sp->subsampling_convert_clines-sp->subsampling_convert_state>=m) - { - sp->subsampling_convert_state+=m; - if (sp->subsampling_convert_state==sp->subsampling_convert_clines) - sp->subsampling_convert_state=0; - return(1); - } - m-=sp->subsampling_convert_clines-sp->subsampling_convert_state; - sp->subsampling_convert_state=0; - } - while (m>=sp->subsampling_convert_clines) - { - if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) - return(0); - m-=sp->subsampling_convert_clines; - } - if (m>0) - { - if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) - return(0); - sp->subsampling_convert_state=m; - } - return(1); + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint32 m; + m=sp->lines_per_strile; + if (sp->subsampling_convert_state!=0) + { + if (sp->subsampling_convert_clines-sp->subsampling_convert_state>=m) + { + sp->subsampling_convert_state+=m; + if (sp->subsampling_convert_state==sp->subsampling_convert_clines) + sp->subsampling_convert_state=0; + return(1); + } + m-=sp->subsampling_convert_clines-sp->subsampling_convert_state; + sp->subsampling_convert_state=0; + } + while (m>=sp->subsampling_convert_clines) + { + if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) + return(0); + m-=sp->subsampling_convert_clines; + } + if (m>0) + { + if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) + return(0); + sp->subsampling_convert_state=m; + } + return(1); } static int OJPEGPreDecodeSkipScanlines(TIFF* tif) { - static const char module[]="OJPEGPreDecodeSkipScanlines"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint32 m; - if (sp->skip_buffer==NULL) - { - sp->skip_buffer=_TIFFmalloc(sp->bytes_per_line); - if (sp->skip_buffer==NULL) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - } - for (m=0; mlines_per_strile; m++) - { - if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&sp->skip_buffer,1)==0) - return(0); - } - return(1); + static const char module[]="OJPEGPreDecodeSkipScanlines"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint32 m; + if (sp->skip_buffer==NULL) + { + sp->skip_buffer=_TIFFmalloc(sp->bytes_per_line); + if (sp->skip_buffer==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + } + for (m=0; mlines_per_strile; m++) + { + if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&sp->skip_buffer,1)==0) + return(0); + } + return(1); } static int OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - (void)s; - if (sp->libjpeg_jpeg_query_style==0) - { - if (OJPEGDecodeRaw(tif,buf,cc)==0) - return(0); - } - else - { - if (OJPEGDecodeScanlines(tif,buf,cc)==0) - return(0); - } - return(1); + static const char module[]="OJPEGDecode"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + (void)s; + if( !sp->decoder_ok ) + { + TIFFErrorExt(tif->tif_clientdata,module,"Cannot decode: decoder not correctly initialized"); + return 0; + } + if (sp->libjpeg_jpeg_query_style==0) + { + if (OJPEGDecodeRaw(tif,buf,cc)==0) + return(0); + } + else + { + if (OJPEGDecodeScanlines(tif,buf,cc)==0) + return(0); + } + return(1); } static int OJPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc) { - static const char module[]="OJPEGDecodeRaw"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8* m; - tmsize_t n; - uint8* oy; - uint8* ocb; - uint8* ocr; - uint8* p; - uint32 q; - uint8* r; - uint8 sx,sy; - if (cc%sp->bytes_per_line!=0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read"); - return(0); - } - assert(cc>0); - m=buf; - n=cc; - do - { - if (sp->subsampling_convert_state==0) - { - if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) - return(0); - } - oy=sp->subsampling_convert_ybuf+sp->subsampling_convert_state*sp->subsampling_ver*sp->subsampling_convert_ylinelen; - ocb=sp->subsampling_convert_cbbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen; - ocr=sp->subsampling_convert_crbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen; - p=m; - for (q=0; qsubsampling_convert_clinelenout; q++) - { - r=oy; - for (sy=0; sysubsampling_ver; sy++) - { - for (sx=0; sxsubsampling_hor; sx++) - *p++=*r++; - r+=sp->subsampling_convert_ylinelen-sp->subsampling_hor; - } - oy+=sp->subsampling_hor; - *p++=*ocb++; - *p++=*ocr++; - } - sp->subsampling_convert_state++; - if (sp->subsampling_convert_state==sp->subsampling_convert_clines) - sp->subsampling_convert_state=0; - m+=sp->bytes_per_line; - n-=sp->bytes_per_line; - } while(n>0); - return(1); + static const char module[]="OJPEGDecodeRaw"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8* m; + tmsize_t n; + uint8* oy; + uint8* ocb; + uint8* ocr; + uint8* p; + uint32 q; + uint8* r; + uint8 sx,sy; + if (cc%sp->bytes_per_line!=0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read"); + return(0); + } + assert(cc>0); + m=buf; + n=cc; + do + { + if (sp->subsampling_convert_state==0) + { + if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) + return(0); + } + oy=sp->subsampling_convert_ybuf+sp->subsampling_convert_state*sp->subsampling_ver*sp->subsampling_convert_ylinelen; + ocb=sp->subsampling_convert_cbbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen; + ocr=sp->subsampling_convert_crbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen; + p=m; + for (q=0; qsubsampling_convert_clinelenout; q++) + { + r=oy; + for (sy=0; sysubsampling_ver; sy++) + { + for (sx=0; sxsubsampling_hor; sx++) + *p++=*r++; + r+=sp->subsampling_convert_ylinelen-sp->subsampling_hor; + } + oy+=sp->subsampling_hor; + *p++=*ocb++; + *p++=*ocr++; + } + sp->subsampling_convert_state++; + if (sp->subsampling_convert_state==sp->subsampling_convert_clines) + sp->subsampling_convert_state=0; + m+=sp->bytes_per_line; + n-=sp->bytes_per_line; + } while(n>0); + return(1); } static int OJPEGDecodeScanlines(TIFF* tif, uint8* buf, tmsize_t cc) { - static const char module[]="OJPEGDecodeScanlines"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8* m; - tmsize_t n; - if (cc%sp->bytes_per_line!=0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read"); - return(0); - } - assert(cc>0); - m=buf; - n=cc; - do - { - if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&m,1)==0) - return(0); - m+=sp->bytes_per_line; - n-=sp->bytes_per_line; - } while(n>0); - return(1); + static const char module[]="OJPEGDecodeScanlines"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8* m; + tmsize_t n; + if (cc%sp->bytes_per_line!=0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read"); + return(0); + } + assert(cc>0); + m=buf; + n=cc; + do + { + if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&m,1)==0) + return(0); + m+=sp->bytes_per_line; + n-=sp->bytes_per_line; + } while(n>0); + return(1); } static void OJPEGPostDecode(TIFF* tif, uint8* buf, tmsize_t cc) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - (void)buf; - (void)cc; - sp->write_curstrile++; - if (sp->write_curstrile%tif->tif_dir.td_stripsperimage==0) - { - assert(sp->libjpeg_session_active!=0); - OJPEGLibjpegSessionAbort(tif); - sp->writeheader_done=0; - } + OJPEGState* sp=(OJPEGState*)tif->tif_data; + (void)buf; + (void)cc; + sp->write_curstrile++; + if (sp->write_curstrile%tif->tif_dir.td_stripsperimage==0) + { + assert(sp->libjpeg_session_active!=0); + OJPEGLibjpegSessionAbort(tif); + sp->writeheader_done=0; + } } static int OJPEGSetupEncode(TIFF* tif) { - static const char module[]="OJPEGSetupEncode"; - TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); - return(0); + static const char module[]="OJPEGSetupEncode"; + TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); + return(0); } static int OJPEGPreEncode(TIFF* tif, uint16 s) { - static const char module[]="OJPEGPreEncode"; - (void)s; - TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); - return(0); + static const char module[]="OJPEGPreEncode"; + (void)s; + TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); + return(0); } static int OJPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) { - static const char module[]="OJPEGEncode"; - (void)buf; - (void)cc; - (void)s; - TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); - return(0); + static const char module[]="OJPEGEncode"; + (void)buf; + (void)cc; + (void)s; + TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); + return(0); } static int OJPEGPostEncode(TIFF* tif) { - static const char module[]="OJPEGPostEncode"; - TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); - return(0); + static const char module[]="OJPEGPostEncode"; + TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead"); + return(0); } static void OJPEGCleanup(TIFF* tif) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - if (sp!=0) - { - tif->tif_tagmethods.vgetfield=sp->vgetparent; - tif->tif_tagmethods.vsetfield=sp->vsetparent; - tif->tif_tagmethods.printdir=sp->printdir; - if (sp->qtable[0]!=0) - _TIFFfree(sp->qtable[0]); - if (sp->qtable[1]!=0) - _TIFFfree(sp->qtable[1]); - if (sp->qtable[2]!=0) - _TIFFfree(sp->qtable[2]); - if (sp->qtable[3]!=0) - _TIFFfree(sp->qtable[3]); - if (sp->dctable[0]!=0) - _TIFFfree(sp->dctable[0]); - if (sp->dctable[1]!=0) - _TIFFfree(sp->dctable[1]); - if (sp->dctable[2]!=0) - _TIFFfree(sp->dctable[2]); - if (sp->dctable[3]!=0) - _TIFFfree(sp->dctable[3]); - if (sp->actable[0]!=0) - _TIFFfree(sp->actable[0]); - if (sp->actable[1]!=0) - _TIFFfree(sp->actable[1]); - if (sp->actable[2]!=0) - _TIFFfree(sp->actable[2]); - if (sp->actable[3]!=0) - _TIFFfree(sp->actable[3]); - if (sp->libjpeg_session_active!=0) - OJPEGLibjpegSessionAbort(tif); - if (sp->subsampling_convert_ycbcrbuf!=0) - _TIFFfree(sp->subsampling_convert_ycbcrbuf); - if (sp->subsampling_convert_ycbcrimage!=0) - _TIFFfree(sp->subsampling_convert_ycbcrimage); - if (sp->skip_buffer!=0) - _TIFFfree(sp->skip_buffer); - _TIFFfree(sp); - tif->tif_data=NULL; - _TIFFSetDefaultCompressionState(tif); - } + OJPEGState* sp=(OJPEGState*)tif->tif_data; + if (sp!=0) + { + tif->tif_tagmethods.vgetfield=sp->vgetparent; + tif->tif_tagmethods.vsetfield=sp->vsetparent; + tif->tif_tagmethods.printdir=sp->printdir; + if (sp->qtable[0]!=0) + _TIFFfree(sp->qtable[0]); + if (sp->qtable[1]!=0) + _TIFFfree(sp->qtable[1]); + if (sp->qtable[2]!=0) + _TIFFfree(sp->qtable[2]); + if (sp->qtable[3]!=0) + _TIFFfree(sp->qtable[3]); + if (sp->dctable[0]!=0) + _TIFFfree(sp->dctable[0]); + if (sp->dctable[1]!=0) + _TIFFfree(sp->dctable[1]); + if (sp->dctable[2]!=0) + _TIFFfree(sp->dctable[2]); + if (sp->dctable[3]!=0) + _TIFFfree(sp->dctable[3]); + if (sp->actable[0]!=0) + _TIFFfree(sp->actable[0]); + if (sp->actable[1]!=0) + _TIFFfree(sp->actable[1]); + if (sp->actable[2]!=0) + _TIFFfree(sp->actable[2]); + if (sp->actable[3]!=0) + _TIFFfree(sp->actable[3]); + if (sp->libjpeg_session_active!=0) + OJPEGLibjpegSessionAbort(tif); + if (sp->subsampling_convert_ycbcrbuf!=0) + _TIFFfree(sp->subsampling_convert_ycbcrbuf); + if (sp->subsampling_convert_ycbcrimage!=0) + _TIFFfree(sp->subsampling_convert_ycbcrimage); + if (sp->skip_buffer!=0) + _TIFFfree(sp->skip_buffer); + _TIFFfree(sp); + tif->tif_data=NULL; + _TIFFSetDefaultCompressionState(tif); + } } static void OJPEGSubsamplingCorrect(TIFF* tif) { - static const char module[]="OJPEGSubsamplingCorrect"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8 mh; - uint8 mv; + static const char module[]="OJPEGSubsamplingCorrect"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 mh; + uint8 mv; _TIFFFillStriles( tif ); - - assert(sp->subsamplingcorrect_done==0); - if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) && - (tif->tif_dir.td_photometric!=PHOTOMETRIC_ITULAB))) - { - if (sp->subsampling_tag!=0) - TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag not appropriate for this Photometric and/or SamplesPerPixel"); - sp->subsampling_hor=1; - sp->subsampling_ver=1; - sp->subsampling_force_desubsampling_inside_decompression=0; - } - else - { - sp->subsamplingcorrect_done=1; - mh=sp->subsampling_hor; - mv=sp->subsampling_ver; - sp->subsamplingcorrect=1; - OJPEGReadHeaderInfoSec(tif); - if (sp->subsampling_force_desubsampling_inside_decompression!=0) - { - sp->subsampling_hor=1; - sp->subsampling_ver=1; - } - sp->subsamplingcorrect=0; - if (((sp->subsampling_hor!=mh) || (sp->subsampling_ver!=mv)) && (sp->subsampling_force_desubsampling_inside_decompression==0)) - { - if (sp->subsampling_tag==0) - TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data [%d,%d] does not match default values [2,2]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver); - else - TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data [%d,%d] does not match subsampling tag values [%d,%d]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver,mh,mv); - } - if (sp->subsampling_force_desubsampling_inside_decompression!=0) - { - if (sp->subsampling_tag==0) - TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data does not match default values [2,2] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression"); - else - TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data does not match subsampling tag values [%d,%d] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression",mh,mv); - } - if (sp->subsampling_force_desubsampling_inside_decompression==0) - { - if (sp->subsampling_horsubsampling_ver) - TIFFWarningExt(tif->tif_clientdata,module,"Subsampling values [%d,%d] are not allowed in TIFF",sp->subsampling_hor,sp->subsampling_ver); - } - } - sp->subsamplingcorrect_done=1; + + assert(sp->subsamplingcorrect_done==0); + if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) && + (tif->tif_dir.td_photometric!=PHOTOMETRIC_ITULAB))) + { + if (sp->subsampling_tag!=0) + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag not appropriate for this Photometric and/or SamplesPerPixel"); + sp->subsampling_hor=1; + sp->subsampling_ver=1; + sp->subsampling_force_desubsampling_inside_decompression=0; + } + else + { + sp->subsamplingcorrect_done=1; + mh=sp->subsampling_hor; + mv=sp->subsampling_ver; + sp->subsamplingcorrect=1; + OJPEGReadHeaderInfoSec(tif); + if (sp->subsampling_force_desubsampling_inside_decompression!=0) + { + sp->subsampling_hor=1; + sp->subsampling_ver=1; + } + sp->subsamplingcorrect=0; + if (((sp->subsampling_hor!=mh) || (sp->subsampling_ver!=mv)) && (sp->subsampling_force_desubsampling_inside_decompression==0)) + { + if (sp->subsampling_tag==0) + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data [%d,%d] does not match default values [2,2]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver); + else + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data [%d,%d] does not match subsampling tag values [%d,%d]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver,mh,mv); + } + if (sp->subsampling_force_desubsampling_inside_decompression!=0) + { + if (sp->subsampling_tag==0) + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data does not match default values [2,2] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression"); + else + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data does not match subsampling tag values [%d,%d] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression",mh,mv); + } + if (sp->subsampling_force_desubsampling_inside_decompression==0) + { + if (sp->subsampling_horsubsampling_ver) + TIFFWarningExt(tif->tif_clientdata,module,"Subsampling values [%d,%d] are not allowed in TIFF",sp->subsampling_hor,sp->subsampling_ver); + } + } + sp->subsamplingcorrect_done=1; } static int OJPEGReadHeaderInfo(TIFF* tif) { - static const char module[]="OJPEGReadHeaderInfo"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - assert(sp->readheader_done==0); - sp->image_width=tif->tif_dir.td_imagewidth; - sp->image_length=tif->tif_dir.td_imagelength; - if isTiled(tif) - { - sp->strile_width=tif->tif_dir.td_tilewidth; - sp->strile_length=tif->tif_dir.td_tilelength; - sp->strile_length_total=((sp->image_length+sp->strile_length-1)/sp->strile_length)*sp->strile_length; - } - else - { - sp->strile_width=sp->image_width; - sp->strile_length=tif->tif_dir.td_rowsperstrip; - sp->strile_length_total=sp->image_length; - } - if (tif->tif_dir.td_samplesperpixel==1) - { - sp->samples_per_pixel=1; - sp->plane_sample_offset=0; - sp->samples_per_pixel_per_plane=sp->samples_per_pixel; - sp->subsampling_hor=1; - sp->subsampling_ver=1; - } - else - { - if (tif->tif_dir.td_samplesperpixel!=3) - { - TIFFErrorExt(tif->tif_clientdata,module,"SamplesPerPixel %d not supported for this compression scheme",sp->samples_per_pixel); - return(0); - } - sp->samples_per_pixel=3; - sp->plane_sample_offset=0; - if (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG) - sp->samples_per_pixel_per_plane=3; - else - sp->samples_per_pixel_per_plane=1; - } - if (sp->strile_lengthimage_length) - { - if (sp->strile_length%(sp->subsampling_ver*8)!=0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length"); - return(0); - } - sp->restart_interval=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8))*(sp->strile_length/(sp->subsampling_ver*8)); - } - if (OJPEGReadHeaderInfoSec(tif)==0) - return(0); - sp->sos_end[0].log=1; - sp->sos_end[0].in_buffer_source=sp->in_buffer_source; - sp->sos_end[0].in_buffer_next_strile=sp->in_buffer_next_strile; - sp->sos_end[0].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo; - sp->sos_end[0].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo; - sp->readheader_done=1; - return(1); + static const char module[]="OJPEGReadHeaderInfo"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(sp->readheader_done==0); + sp->image_width=tif->tif_dir.td_imagewidth; + sp->image_length=tif->tif_dir.td_imagelength; + if isTiled(tif) + { + sp->strile_width=tif->tif_dir.td_tilewidth; + sp->strile_length=tif->tif_dir.td_tilelength; + sp->strile_length_total=((sp->image_length+sp->strile_length-1)/sp->strile_length)*sp->strile_length; + } + else + { + sp->strile_width=sp->image_width; + sp->strile_length=tif->tif_dir.td_rowsperstrip; + sp->strile_length_total=sp->image_length; + } + if (tif->tif_dir.td_samplesperpixel==1) + { + sp->samples_per_pixel=1; + sp->plane_sample_offset=0; + sp->samples_per_pixel_per_plane=sp->samples_per_pixel; + sp->subsampling_hor=1; + sp->subsampling_ver=1; + } + else + { + if (tif->tif_dir.td_samplesperpixel!=3) + { + TIFFErrorExt(tif->tif_clientdata,module,"SamplesPerPixel %d not supported for this compression scheme",sp->samples_per_pixel); + return(0); + } + sp->samples_per_pixel=3; + sp->plane_sample_offset=0; + if (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG) + sp->samples_per_pixel_per_plane=3; + else + sp->samples_per_pixel_per_plane=1; + } + if (sp->strile_lengthimage_length) + { + if (sp->strile_length%(sp->subsampling_ver*8)!=0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length"); + return(0); + } + sp->restart_interval=(uint16)(((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8))*(sp->strile_length/(sp->subsampling_ver*8))); + } + if (OJPEGReadHeaderInfoSec(tif)==0) + return(0); + sp->sos_end[0].log=1; + sp->sos_end[0].in_buffer_source=sp->in_buffer_source; + sp->sos_end[0].in_buffer_next_strile=sp->in_buffer_next_strile; + sp->sos_end[0].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo; + sp->sos_end[0].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo; + sp->readheader_done=1; + return(1); } static int OJPEGReadSecondarySos(TIFF* tif, uint16 s) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8 m; - assert(s>0); - assert(s<3); - assert(sp->sos_end[0].log!=0); - assert(sp->sos_end[s].log==0); - sp->plane_sample_offset=s-1; - while(sp->sos_end[sp->plane_sample_offset].log==0) - sp->plane_sample_offset--; - sp->in_buffer_source=sp->sos_end[sp->plane_sample_offset].in_buffer_source; - sp->in_buffer_next_strile=sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile; - sp->in_buffer_file_pos=sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos; - sp->in_buffer_file_pos_log=0; - sp->in_buffer_file_togo=sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo; - sp->in_buffer_togo=0; - sp->in_buffer_cur=0; - while(sp->plane_sample_offsetplane_sample_offset++; - if (OJPEGReadHeaderInfoSecStreamSos(tif)==0) - return(0); - sp->sos_end[sp->plane_sample_offset].log=1; - sp->sos_end[sp->plane_sample_offset].in_buffer_source=sp->in_buffer_source; - sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile=sp->in_buffer_next_strile; - sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo; - sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo; - } - return(1); + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + assert(s>0); + assert(s<3); + assert(sp->sos_end[0].log!=0); + assert(sp->sos_end[s].log==0); + sp->plane_sample_offset=(uint8)(s-1); + while(sp->sos_end[sp->plane_sample_offset].log==0) + sp->plane_sample_offset--; + sp->in_buffer_source=sp->sos_end[sp->plane_sample_offset].in_buffer_source; + sp->in_buffer_next_strile=sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile; + sp->in_buffer_file_pos=sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos; + sp->in_buffer_file_pos_log=0; + sp->in_buffer_file_togo=sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo; + sp->in_buffer_togo=0; + sp->in_buffer_cur=0; + while(sp->plane_sample_offsetplane_sample_offset++; + if (OJPEGReadHeaderInfoSecStreamSos(tif)==0) + return(0); + sp->sos_end[sp->plane_sample_offset].log=1; + sp->sos_end[sp->plane_sample_offset].in_buffer_source=sp->in_buffer_source; + sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile=sp->in_buffer_next_strile; + sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo; + sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo; + } + return(1); } static int OJPEGWriteHeaderInfo(TIFF* tif) { - static const char module[]="OJPEGWriteHeaderInfo"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8** m; - uint32 n; - /* if a previous attempt failed, don't try again */ - if (sp->libjpeg_session_active != 0) - return 0; - sp->out_state=ososSoi; - sp->restart_index=0; - jpeg_std_error(&(sp->libjpeg_jpeg_error_mgr)); - sp->libjpeg_jpeg_error_mgr.output_message=OJPEGLibjpegJpegErrorMgrOutputMessage; - sp->libjpeg_jpeg_error_mgr.error_exit=OJPEGLibjpegJpegErrorMgrErrorExit; - sp->libjpeg_jpeg_decompress_struct.err=&(sp->libjpeg_jpeg_error_mgr); - sp->libjpeg_jpeg_decompress_struct.client_data=(void*)tif; - if (jpeg_create_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0) - return(0); - sp->libjpeg_session_active=1; - sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=0; - sp->libjpeg_jpeg_source_mgr.init_source=OJPEGLibjpegJpegSourceMgrInitSource; - sp->libjpeg_jpeg_source_mgr.fill_input_buffer=OJPEGLibjpegJpegSourceMgrFillInputBuffer; - sp->libjpeg_jpeg_source_mgr.skip_input_data=OJPEGLibjpegJpegSourceMgrSkipInputData; - sp->libjpeg_jpeg_source_mgr.resync_to_restart=OJPEGLibjpegJpegSourceMgrResyncToRestart; - sp->libjpeg_jpeg_source_mgr.term_source=OJPEGLibjpegJpegSourceMgrTermSource; - sp->libjpeg_jpeg_decompress_struct.src=&(sp->libjpeg_jpeg_source_mgr); - if (jpeg_read_header_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),1)==0) - return(0); - if ((sp->subsampling_force_desubsampling_inside_decompression==0) && (sp->samples_per_pixel_per_plane>1)) - { - sp->libjpeg_jpeg_decompress_struct.raw_data_out=1; + static const char module[]="OJPEGWriteHeaderInfo"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8** m; + uint32 n; + /* if a previous attempt failed, don't try again */ + if (sp->libjpeg_session_active != 0) + return 0; + sp->out_state=ososSoi; + sp->restart_index=0; + jpeg_std_error(&(sp->libjpeg_jpeg_error_mgr)); + sp->libjpeg_jpeg_error_mgr.output_message=OJPEGLibjpegJpegErrorMgrOutputMessage; + sp->libjpeg_jpeg_error_mgr.error_exit=OJPEGLibjpegJpegErrorMgrErrorExit; + sp->libjpeg_jpeg_decompress_struct.err=&(sp->libjpeg_jpeg_error_mgr); + sp->libjpeg_jpeg_decompress_struct.client_data=(void*)tif; + if (jpeg_create_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0) + return(0); + sp->libjpeg_session_active=1; + sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=0; + sp->libjpeg_jpeg_source_mgr.init_source=OJPEGLibjpegJpegSourceMgrInitSource; + sp->libjpeg_jpeg_source_mgr.fill_input_buffer=OJPEGLibjpegJpegSourceMgrFillInputBuffer; + sp->libjpeg_jpeg_source_mgr.skip_input_data=OJPEGLibjpegJpegSourceMgrSkipInputData; + sp->libjpeg_jpeg_source_mgr.resync_to_restart=OJPEGLibjpegJpegSourceMgrResyncToRestart; + sp->libjpeg_jpeg_source_mgr.term_source=OJPEGLibjpegJpegSourceMgrTermSource; + sp->libjpeg_jpeg_decompress_struct.src=&(sp->libjpeg_jpeg_source_mgr); + if (jpeg_read_header_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),1)==0) + return(0); + if ((sp->subsampling_force_desubsampling_inside_decompression==0) && (sp->samples_per_pixel_per_plane>1)) + { + sp->libjpeg_jpeg_decompress_struct.raw_data_out=1; #if JPEG_LIB_VERSION >= 70 - sp->libjpeg_jpeg_decompress_struct.do_fancy_upsampling=FALSE; + sp->libjpeg_jpeg_decompress_struct.do_fancy_upsampling=FALSE; #endif - sp->libjpeg_jpeg_query_style=0; - if (sp->subsampling_convert_log==0) - { - assert(sp->subsampling_convert_ycbcrbuf==0); - assert(sp->subsampling_convert_ycbcrimage==0); - sp->subsampling_convert_ylinelen=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8)*sp->subsampling_hor*8); - sp->subsampling_convert_ylines=sp->subsampling_ver*8; - sp->subsampling_convert_clinelen=sp->subsampling_convert_ylinelen/sp->subsampling_hor; - sp->subsampling_convert_clines=8; - sp->subsampling_convert_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines; - sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines; - sp->subsampling_convert_ycbcrbuflen=sp->subsampling_convert_ybuflen+2*sp->subsampling_convert_cbuflen; - sp->subsampling_convert_ycbcrbuf=_TIFFmalloc(sp->subsampling_convert_ycbcrbuflen); - if (sp->subsampling_convert_ycbcrbuf==0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - sp->subsampling_convert_ybuf=sp->subsampling_convert_ycbcrbuf; - sp->subsampling_convert_cbbuf=sp->subsampling_convert_ybuf+sp->subsampling_convert_ybuflen; - sp->subsampling_convert_crbuf=sp->subsampling_convert_cbbuf+sp->subsampling_convert_cbuflen; - sp->subsampling_convert_ycbcrimagelen=3+sp->subsampling_convert_ylines+2*sp->subsampling_convert_clines; - sp->subsampling_convert_ycbcrimage=_TIFFmalloc(sp->subsampling_convert_ycbcrimagelen*sizeof(uint8*)); - if (sp->subsampling_convert_ycbcrimage==0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - m=sp->subsampling_convert_ycbcrimage; - *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3); - *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines); - *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines+sp->subsampling_convert_clines); - for (n=0; nsubsampling_convert_ylines; n++) - *m++=sp->subsampling_convert_ybuf+n*sp->subsampling_convert_ylinelen; - for (n=0; nsubsampling_convert_clines; n++) - *m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen; - for (n=0; nsubsampling_convert_clines; n++) - *m++=sp->subsampling_convert_crbuf+n*sp->subsampling_convert_clinelen; - sp->subsampling_convert_clinelenout=((sp->strile_width+sp->subsampling_hor-1)/sp->subsampling_hor); - sp->subsampling_convert_state=0; - sp->bytes_per_line=sp->subsampling_convert_clinelenout*(sp->subsampling_ver*sp->subsampling_hor+2); - sp->lines_per_strile=((sp->strile_length+sp->subsampling_ver-1)/sp->subsampling_ver); - sp->subsampling_convert_log=1; - } - } - else - { - sp->libjpeg_jpeg_decompress_struct.jpeg_color_space=JCS_UNKNOWN; - sp->libjpeg_jpeg_decompress_struct.out_color_space=JCS_UNKNOWN; - sp->libjpeg_jpeg_query_style=1; - sp->bytes_per_line=sp->samples_per_pixel_per_plane*sp->strile_width; - sp->lines_per_strile=sp->strile_length; - } - if (jpeg_start_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0) - return(0); - sp->writeheader_done=1; - return(1); + sp->libjpeg_jpeg_query_style=0; + if (sp->subsampling_convert_log==0) + { + assert(sp->subsampling_convert_ycbcrbuf==0); + assert(sp->subsampling_convert_ycbcrimage==0); + sp->subsampling_convert_ylinelen=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8)*sp->subsampling_hor*8); + sp->subsampling_convert_ylines=sp->subsampling_ver*8; + sp->subsampling_convert_clinelen=sp->subsampling_convert_ylinelen/sp->subsampling_hor; + sp->subsampling_convert_clines=8; + sp->subsampling_convert_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines; + sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines; + sp->subsampling_convert_ycbcrbuflen=sp->subsampling_convert_ybuflen+2*sp->subsampling_convert_cbuflen; + sp->subsampling_convert_ycbcrbuf=_TIFFmalloc(sp->subsampling_convert_ycbcrbuflen); + if (sp->subsampling_convert_ycbcrbuf==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + sp->subsampling_convert_ybuf=sp->subsampling_convert_ycbcrbuf; + sp->subsampling_convert_cbbuf=sp->subsampling_convert_ybuf+sp->subsampling_convert_ybuflen; + sp->subsampling_convert_crbuf=sp->subsampling_convert_cbbuf+sp->subsampling_convert_cbuflen; + sp->subsampling_convert_ycbcrimagelen=3+sp->subsampling_convert_ylines+2*sp->subsampling_convert_clines; + sp->subsampling_convert_ycbcrimage=_TIFFmalloc(sp->subsampling_convert_ycbcrimagelen*sizeof(uint8*)); + if (sp->subsampling_convert_ycbcrimage==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + m=sp->subsampling_convert_ycbcrimage; + *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3); + *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines); + *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines+sp->subsampling_convert_clines); + for (n=0; nsubsampling_convert_ylines; n++) + *m++=sp->subsampling_convert_ybuf+n*sp->subsampling_convert_ylinelen; + for (n=0; nsubsampling_convert_clines; n++) + *m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen; + for (n=0; nsubsampling_convert_clines; n++) + *m++=sp->subsampling_convert_crbuf+n*sp->subsampling_convert_clinelen; + sp->subsampling_convert_clinelenout=((sp->strile_width+sp->subsampling_hor-1)/sp->subsampling_hor); + sp->subsampling_convert_state=0; + sp->bytes_per_line=sp->subsampling_convert_clinelenout*(sp->subsampling_ver*sp->subsampling_hor+2); + sp->lines_per_strile=((sp->strile_length+sp->subsampling_ver-1)/sp->subsampling_ver); + sp->subsampling_convert_log=1; + } + } + else + { + sp->libjpeg_jpeg_decompress_struct.jpeg_color_space=JCS_UNKNOWN; + sp->libjpeg_jpeg_decompress_struct.out_color_space=JCS_UNKNOWN; + sp->libjpeg_jpeg_query_style=1; + sp->bytes_per_line=sp->samples_per_pixel_per_plane*sp->strile_width; + sp->lines_per_strile=sp->strile_length; + } + if (jpeg_start_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0) + return(0); + sp->writeheader_done=1; + return(1); } static void OJPEGLibjpegSessionAbort(TIFF* tif) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - assert(sp->libjpeg_session_active!=0); - jpeg_destroy((jpeg_common_struct*)(&(sp->libjpeg_jpeg_decompress_struct))); - sp->libjpeg_session_active=0; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(sp->libjpeg_session_active!=0); + jpeg_destroy((jpeg_common_struct*)(&(sp->libjpeg_jpeg_decompress_struct))); + sp->libjpeg_session_active=0; } static int OJPEGReadHeaderInfoSec(TIFF* tif) { - static const char module[]="OJPEGReadHeaderInfoSec"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8 m; - uint16 n; - uint8 o; - if (sp->file_size==0) - sp->file_size=TIFFGetFileSize(tif); - if (sp->jpeg_interchange_format!=0) - { - if (sp->jpeg_interchange_format>=sp->file_size) - { - sp->jpeg_interchange_format=0; - sp->jpeg_interchange_format_length=0; - } - else - { - if ((sp->jpeg_interchange_format_length==0) || (sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size)) - sp->jpeg_interchange_format_length=sp->file_size-sp->jpeg_interchange_format; - } - } - sp->in_buffer_source=osibsNotSetYet; - sp->in_buffer_next_strile=0; - sp->in_buffer_strile_count=tif->tif_dir.td_nstrips; - sp->in_buffer_file_togo=0; - sp->in_buffer_togo=0; - do - { - if (OJPEGReadBytePeek(sp,&m)==0) - return(0); - if (m!=255) - break; - OJPEGReadByteAdvance(sp); - do - { - if (OJPEGReadByte(sp,&m)==0) - return(0); - } while(m==255); - switch(m) - { - case JPEG_MARKER_SOI: - /* this type of marker has no data, and should be skipped */ - break; - case JPEG_MARKER_COM: - case JPEG_MARKER_APP0: - case JPEG_MARKER_APP0+1: - case JPEG_MARKER_APP0+2: - case JPEG_MARKER_APP0+3: - case JPEG_MARKER_APP0+4: - case JPEG_MARKER_APP0+5: - case JPEG_MARKER_APP0+6: - case JPEG_MARKER_APP0+7: - case JPEG_MARKER_APP0+8: - case JPEG_MARKER_APP0+9: - case JPEG_MARKER_APP0+10: - case JPEG_MARKER_APP0+11: - case JPEG_MARKER_APP0+12: - case JPEG_MARKER_APP0+13: - case JPEG_MARKER_APP0+14: - case JPEG_MARKER_APP0+15: - /* this type of marker has data, but it has no use to us (and no place here) and should be skipped */ - if (OJPEGReadWord(sp,&n)==0) - return(0); - if (n<2) - { - if (sp->subsamplingcorrect==0) - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data"); - return(0); - } - if (n>2) - OJPEGReadSkip(sp,n-2); - break; - case JPEG_MARKER_DRI: - if (OJPEGReadHeaderInfoSecStreamDri(tif)==0) - return(0); - break; - case JPEG_MARKER_DQT: - if (OJPEGReadHeaderInfoSecStreamDqt(tif)==0) - return(0); - break; - case JPEG_MARKER_DHT: - if (OJPEGReadHeaderInfoSecStreamDht(tif)==0) - return(0); - break; - case JPEG_MARKER_SOF0: - case JPEG_MARKER_SOF1: - case JPEG_MARKER_SOF3: - if (OJPEGReadHeaderInfoSecStreamSof(tif,m)==0) - return(0); - if (sp->subsamplingcorrect!=0) - return(1); - break; - case JPEG_MARKER_SOS: - if (sp->subsamplingcorrect!=0) - return(1); - assert(sp->plane_sample_offset==0); - if (OJPEGReadHeaderInfoSecStreamSos(tif)==0) - return(0); - break; - default: - TIFFErrorExt(tif->tif_clientdata,module,"Unknown marker type %d in JPEG data",m); - return(0); - } - } while(m!=JPEG_MARKER_SOS); - if (sp->subsamplingcorrect) - return(1); - if (sp->sof_log==0) - { - if (OJPEGReadHeaderInfoSecTablesQTable(tif)==0) - return(0); - sp->sof_marker_id=JPEG_MARKER_SOF0; - for (o=0; osamples_per_pixel; o++) - sp->sof_c[o]=o; - sp->sof_hv[0]=((sp->subsampling_hor<<4)|sp->subsampling_ver); - for (o=1; osamples_per_pixel; o++) - sp->sof_hv[o]=17; - sp->sof_x=sp->strile_width; - sp->sof_y=sp->strile_length_total; - sp->sof_log=1; - if (OJPEGReadHeaderInfoSecTablesDcTable(tif)==0) - return(0); - if (OJPEGReadHeaderInfoSecTablesAcTable(tif)==0) - return(0); - for (o=1; osamples_per_pixel; o++) - sp->sos_cs[o]=o; - } - return(1); + static const char module[]="OJPEGReadHeaderInfoSec"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + uint16 n; + uint8 o; + if (sp->file_size==0) + sp->file_size=TIFFGetFileSize(tif); + if (sp->jpeg_interchange_format!=0) + { + if (sp->jpeg_interchange_format>=sp->file_size) + { + sp->jpeg_interchange_format=0; + sp->jpeg_interchange_format_length=0; + } + else + { + if ((sp->jpeg_interchange_format_length==0) || (sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size)) + sp->jpeg_interchange_format_length=sp->file_size-sp->jpeg_interchange_format; + } + } + sp->in_buffer_source=osibsNotSetYet; + sp->in_buffer_next_strile=0; + sp->in_buffer_strile_count=tif->tif_dir.td_nstrips; + sp->in_buffer_file_togo=0; + sp->in_buffer_togo=0; + do + { + if (OJPEGReadBytePeek(sp,&m)==0) + return(0); + if (m!=255) + break; + OJPEGReadByteAdvance(sp); + do + { + if (OJPEGReadByte(sp,&m)==0) + return(0); + } while(m==255); + switch(m) + { + case JPEG_MARKER_SOI: + /* this type of marker has no data, and should be skipped */ + break; + case JPEG_MARKER_COM: + case JPEG_MARKER_APP0: + case JPEG_MARKER_APP0+1: + case JPEG_MARKER_APP0+2: + case JPEG_MARKER_APP0+3: + case JPEG_MARKER_APP0+4: + case JPEG_MARKER_APP0+5: + case JPEG_MARKER_APP0+6: + case JPEG_MARKER_APP0+7: + case JPEG_MARKER_APP0+8: + case JPEG_MARKER_APP0+9: + case JPEG_MARKER_APP0+10: + case JPEG_MARKER_APP0+11: + case JPEG_MARKER_APP0+12: + case JPEG_MARKER_APP0+13: + case JPEG_MARKER_APP0+14: + case JPEG_MARKER_APP0+15: + /* this type of marker has data, but it has no use to us (and no place here) and should be skipped */ + if (OJPEGReadWord(sp,&n)==0) + return(0); + if (n<2) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data"); + return(0); + } + if (n>2) + OJPEGReadSkip(sp,n-2); + break; + case JPEG_MARKER_DRI: + if (OJPEGReadHeaderInfoSecStreamDri(tif)==0) + return(0); + break; + case JPEG_MARKER_DQT: + if (OJPEGReadHeaderInfoSecStreamDqt(tif)==0) + return(0); + break; + case JPEG_MARKER_DHT: + if (OJPEGReadHeaderInfoSecStreamDht(tif)==0) + return(0); + break; + case JPEG_MARKER_SOF0: + case JPEG_MARKER_SOF1: + case JPEG_MARKER_SOF3: + if (OJPEGReadHeaderInfoSecStreamSof(tif,m)==0) + return(0); + if (sp->subsamplingcorrect!=0) + return(1); + break; + case JPEG_MARKER_SOS: + if (sp->subsamplingcorrect!=0) + return(1); + assert(sp->plane_sample_offset==0); + if (OJPEGReadHeaderInfoSecStreamSos(tif)==0) + return(0); + break; + default: + TIFFErrorExt(tif->tif_clientdata,module,"Unknown marker type %d in JPEG data",m); + return(0); + } + } while(m!=JPEG_MARKER_SOS); + if (sp->subsamplingcorrect) + return(1); + if (sp->sof_log==0) + { + if (OJPEGReadHeaderInfoSecTablesQTable(tif)==0) + return(0); + sp->sof_marker_id=JPEG_MARKER_SOF0; + for (o=0; osamples_per_pixel; o++) + sp->sof_c[o]=o; + sp->sof_hv[0]=((sp->subsampling_hor<<4)|sp->subsampling_ver); + for (o=1; osamples_per_pixel; o++) + sp->sof_hv[o]=17; + sp->sof_x=sp->strile_width; + sp->sof_y=sp->strile_length_total; + sp->sof_log=1; + if (OJPEGReadHeaderInfoSecTablesDcTable(tif)==0) + return(0); + if (OJPEGReadHeaderInfoSecTablesAcTable(tif)==0) + return(0); + for (o=1; osamples_per_pixel; o++) + sp->sos_cs[o]=o; + } + return(1); } static int OJPEGReadHeaderInfoSecStreamDri(TIFF* tif) { - /* this could easilly cause trouble in some cases... but no such cases have occured sofar */ - static const char module[]="OJPEGReadHeaderInfoSecStreamDri"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint16 m; - if (OJPEGReadWord(sp,&m)==0) - return(0); - if (m!=4) - { - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DRI marker in JPEG data"); - return(0); - } - if (OJPEGReadWord(sp,&m)==0) - return(0); - sp->restart_interval=m; - return(1); + /* This could easily cause trouble in some cases... but no such cases have + occurred so far */ + static const char module[]="OJPEGReadHeaderInfoSecStreamDri"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint16 m; + if (OJPEGReadWord(sp,&m)==0) + return(0); + if (m!=4) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DRI marker in JPEG data"); + return(0); + } + if (OJPEGReadWord(sp,&m)==0) + return(0); + sp->restart_interval=m; + return(1); } static int OJPEGReadHeaderInfoSecStreamDqt(TIFF* tif) { - /* this is a table marker, and it is to be saved as a whole for exact pushing on the jpeg stream later on */ - static const char module[]="OJPEGReadHeaderInfoSecStreamDqt"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint16 m; - uint32 na; - uint8* nb; - uint8 o; - if (OJPEGReadWord(sp,&m)==0) - return(0); - if (m<=2) - { - if (sp->subsamplingcorrect==0) - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data"); - return(0); - } - if (sp->subsamplingcorrect!=0) - OJPEGReadSkip(sp,m-2); - else - { - m-=2; - do - { - if (m<65) - { - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data"); - return(0); - } - na=sizeof(uint32)+69; - nb=_TIFFmalloc(na); - if (nb==0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - *(uint32*)nb=na; - nb[sizeof(uint32)]=255; - nb[sizeof(uint32)+1]=JPEG_MARKER_DQT; - nb[sizeof(uint32)+2]=0; - nb[sizeof(uint32)+3]=67; - if (OJPEGReadBlock(sp,65,&nb[sizeof(uint32)+4])==0) { - _TIFFfree(nb); - return(0); - } - o=nb[sizeof(uint32)+4]&15; - if (3tif_clientdata,module,"Corrupt DQT marker in JPEG data"); - _TIFFfree(nb); - return(0); - } - if (sp->qtable[o]!=0) - _TIFFfree(sp->qtable[o]); - sp->qtable[o]=nb; - m-=65; - } while(m>0); - } - return(1); + /* this is a table marker, and it is to be saved as a whole for exact pushing on the jpeg stream later on */ + static const char module[]="OJPEGReadHeaderInfoSecStreamDqt"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint16 m; + uint32 na; + uint8* nb; + uint8 o; + if (OJPEGReadWord(sp,&m)==0) + return(0); + if (m<=2) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data"); + return(0); + } + if (sp->subsamplingcorrect!=0) + OJPEGReadSkip(sp,m-2); + else + { + m-=2; + do + { + if (m<65) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data"); + return(0); + } + na=sizeof(uint32)+69; + nb=_TIFFmalloc(na); + if (nb==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + *(uint32*)nb=na; + nb[sizeof(uint32)]=255; + nb[sizeof(uint32)+1]=JPEG_MARKER_DQT; + nb[sizeof(uint32)+2]=0; + nb[sizeof(uint32)+3]=67; + if (OJPEGReadBlock(sp,65,&nb[sizeof(uint32)+4])==0) { + _TIFFfree(nb); + return(0); + } + o=nb[sizeof(uint32)+4]&15; + if (3tif_clientdata,module,"Corrupt DQT marker in JPEG data"); + _TIFFfree(nb); + return(0); + } + if (sp->qtable[o]!=0) + _TIFFfree(sp->qtable[o]); + sp->qtable[o]=nb; + m-=65; + } while(m>0); + } + return(1); } static int OJPEGReadHeaderInfoSecStreamDht(TIFF* tif) { - /* this is a table marker, and it is to be saved as a whole for exact pushing on the jpeg stream later on */ - /* TODO: the following assumes there is only one table in this marker... but i'm not quite sure that assumption is guaranteed correct */ - static const char module[]="OJPEGReadHeaderInfoSecStreamDht"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint16 m; - uint32 na; - uint8* nb; - uint8 o; - if (OJPEGReadWord(sp,&m)==0) - return(0); - if (m<=2) - { - if (sp->subsamplingcorrect==0) - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data"); - return(0); - } - if (sp->subsamplingcorrect!=0) - { - OJPEGReadSkip(sp,m-2); - } - else - { - na=sizeof(uint32)+2+m; - nb=_TIFFmalloc(na); - if (nb==0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - *(uint32*)nb=na; - nb[sizeof(uint32)]=255; - nb[sizeof(uint32)+1]=JPEG_MARKER_DHT; - nb[sizeof(uint32)+2]=(m>>8); - nb[sizeof(uint32)+3]=(m&255); - if (OJPEGReadBlock(sp,m-2,&nb[sizeof(uint32)+4])==0) - return(0); - o=nb[sizeof(uint32)+4]; - if ((o&240)==0) - { - if (3tif_clientdata,module,"Corrupt DHT marker in JPEG data"); - return(0); - } - if (sp->dctable[o]!=0) - _TIFFfree(sp->dctable[o]); - sp->dctable[o]=nb; - } - else - { - if ((o&240)!=16) - { - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data"); - return(0); - } - o&=15; - if (3tif_clientdata,module,"Corrupt DHT marker in JPEG data"); - return(0); - } - if (sp->actable[o]!=0) - _TIFFfree(sp->actable[o]); - sp->actable[o]=nb; - } - } - return(1); + /* this is a table marker, and it is to be saved as a whole for exact pushing on the jpeg stream later on */ + /* TODO: the following assumes there is only one table in this marker... but i'm not quite sure that assumption is guaranteed correct */ + static const char module[]="OJPEGReadHeaderInfoSecStreamDht"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint16 m; + uint32 na; + uint8* nb; + uint8 o; + if (OJPEGReadWord(sp,&m)==0) + return(0); + if (m<=2) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data"); + return(0); + } + if (sp->subsamplingcorrect!=0) + { + OJPEGReadSkip(sp,m-2); + } + else + { + na=sizeof(uint32)+2+m; + nb=_TIFFmalloc(na); + if (nb==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + *(uint32*)nb=na; + nb[sizeof(uint32)]=255; + nb[sizeof(uint32)+1]=JPEG_MARKER_DHT; + nb[sizeof(uint32)+2]=(m>>8); + nb[sizeof(uint32)+3]=(m&255); + if (OJPEGReadBlock(sp,m-2,&nb[sizeof(uint32)+4])==0) { + _TIFFfree(nb); + return(0); + } + o=nb[sizeof(uint32)+4]; + if ((o&240)==0) + { + if (3tif_clientdata,module,"Corrupt DHT marker in JPEG data"); + _TIFFfree(nb); + return(0); + } + if (sp->dctable[o]!=0) + _TIFFfree(sp->dctable[o]); + sp->dctable[o]=nb; + } + else + { + if ((o&240)!=16) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data"); + _TIFFfree(nb); + return(0); + } + o&=15; + if (3tif_clientdata,module,"Corrupt DHT marker in JPEG data"); + _TIFFfree(nb); + return(0); + } + if (sp->actable[o]!=0) + _TIFFfree(sp->actable[o]); + sp->actable[o]=nb; + } + } + return(1); } static int OJPEGReadHeaderInfoSecStreamSof(TIFF* tif, uint8 marker_id) { - /* this marker needs to be checked, and part of its data needs to be saved for regeneration later on */ - static const char module[]="OJPEGReadHeaderInfoSecStreamSof"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint16 m; - uint16 n; - uint8 o; - uint16 p; - uint16 q; - if (sp->sof_log!=0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data"); - return(0); - } - if (sp->subsamplingcorrect==0) - sp->sof_marker_id=marker_id; - /* Lf: data length */ - if (OJPEGReadWord(sp,&m)==0) - return(0); - if (m<11) - { - if (sp->subsamplingcorrect==0) - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); - return(0); - } - m-=8; - if (m%3!=0) - { - if (sp->subsamplingcorrect==0) - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); - return(0); - } - n=m/3; - if (sp->subsamplingcorrect==0) - { - if (n!=sp->samples_per_pixel) - { - TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of samples"); - return(0); - } - } - /* P: Sample precision */ - if (OJPEGReadByte(sp,&o)==0) - return(0); - if (o!=8) - { - if (sp->subsamplingcorrect==0) - TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of bits per sample"); - return(0); - } - /* Y: Number of lines, X: Number of samples per line */ - if (sp->subsamplingcorrect) - OJPEGReadSkip(sp,4); - else - { - /* Y: Number of lines */ - if (OJPEGReadWord(sp,&p)==0) - return(0); - if (((uint32)pimage_length) && ((uint32)pstrile_length_total)) - { - TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected height"); - return(0); - } - sp->sof_y=p; - /* X: Number of samples per line */ - if (OJPEGReadWord(sp,&p)==0) - return(0); - if (((uint32)pimage_width) && ((uint32)pstrile_width)) - { - TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected width"); - return(0); - } - if ((uint32)p>sp->strile_width) - { - TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data image width exceeds expected image width"); - return(0); - } - sp->sof_x=p; - } - /* Nf: Number of image components in frame */ - if (OJPEGReadByte(sp,&o)==0) - return(0); - if (o!=n) - { - if (sp->subsamplingcorrect==0) - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); - return(0); - } - /* per component stuff */ - /* TODO: double-check that flow implies that n cannot be as big as to make us overflow sof_c, sof_hv and sof_tq arrays */ - for (q=0; qsubsamplingcorrect==0) - sp->sof_c[q]=o; - /* H: Horizontal sampling factor, and V: Vertical sampling factor */ - if (OJPEGReadByte(sp,&o)==0) - return(0); - if (sp->subsamplingcorrect!=0) - { - if (q==0) - { - sp->subsampling_hor=(o>>4); - sp->subsampling_ver=(o&15); - if (((sp->subsampling_hor!=1) && (sp->subsampling_hor!=2) && (sp->subsampling_hor!=4)) || - ((sp->subsampling_ver!=1) && (sp->subsampling_ver!=2) && (sp->subsampling_ver!=4))) - sp->subsampling_force_desubsampling_inside_decompression=1; - } - else - { - if (o!=17) - sp->subsampling_force_desubsampling_inside_decompression=1; - } - } - else - { - sp->sof_hv[q]=o; - if (sp->subsampling_force_desubsampling_inside_decompression==0) - { - if (q==0) - { - if (o!=((sp->subsampling_hor<<4)|sp->subsampling_ver)) - { - TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values"); - return(0); - } - } - else - { - if (o!=17) - { - TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values"); - return(0); - } - } - } - } - /* Tq: Quantization table destination selector */ - if (OJPEGReadByte(sp,&o)==0) - return(0); - if (sp->subsamplingcorrect==0) - sp->sof_tq[q]=o; - } - if (sp->subsamplingcorrect==0) - sp->sof_log=1; - return(1); + /* this marker needs to be checked, and part of its data needs to be saved for regeneration later on */ + static const char module[]="OJPEGReadHeaderInfoSecStreamSof"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint16 m; + uint16 n; + uint8 o; + uint16 p; + uint16 q; + if (sp->sof_log!=0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data"); + return(0); + } + if (sp->subsamplingcorrect==0) + sp->sof_marker_id=marker_id; + /* Lf: data length */ + if (OJPEGReadWord(sp,&m)==0) + return(0); + if (m<11) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); + return(0); + } + m-=8; + if (m%3!=0) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); + return(0); + } + n=m/3; + if (sp->subsamplingcorrect==0) + { + if (n!=sp->samples_per_pixel) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of samples"); + return(0); + } + } + /* P: Sample precision */ + if (OJPEGReadByte(sp,&o)==0) + return(0); + if (o!=8) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of bits per sample"); + return(0); + } + /* Y: Number of lines, X: Number of samples per line */ + if (sp->subsamplingcorrect) + OJPEGReadSkip(sp,4); + else + { + /* Y: Number of lines */ + if (OJPEGReadWord(sp,&p)==0) + return(0); + if (((uint32)pimage_length) && ((uint32)pstrile_length_total)) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected height"); + return(0); + } + sp->sof_y=p; + /* X: Number of samples per line */ + if (OJPEGReadWord(sp,&p)==0) + return(0); + if (((uint32)pimage_width) && ((uint32)pstrile_width)) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected width"); + return(0); + } + if ((uint32)p>sp->strile_width) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data image width exceeds expected image width"); + return(0); + } + sp->sof_x=p; + } + /* Nf: Number of image components in frame */ + if (OJPEGReadByte(sp,&o)==0) + return(0); + if (o!=n) + { + if (sp->subsamplingcorrect==0) + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data"); + return(0); + } + /* per component stuff */ + /* TODO: double-check that flow implies that n cannot be as big as to make us overflow sof_c, sof_hv and sof_tq arrays */ + for (q=0; qsubsamplingcorrect==0) + sp->sof_c[q]=o; + /* H: Horizontal sampling factor, and V: Vertical sampling factor */ + if (OJPEGReadByte(sp,&o)==0) + return(0); + if (sp->subsamplingcorrect!=0) + { + if (q==0) + { + sp->subsampling_hor=(o>>4); + sp->subsampling_ver=(o&15); + if (((sp->subsampling_hor!=1) && (sp->subsampling_hor!=2) && (sp->subsampling_hor!=4)) || + ((sp->subsampling_ver!=1) && (sp->subsampling_ver!=2) && (sp->subsampling_ver!=4))) + sp->subsampling_force_desubsampling_inside_decompression=1; + } + else + { + if (o!=17) + sp->subsampling_force_desubsampling_inside_decompression=1; + } + } + else + { + sp->sof_hv[q]=o; + if (sp->subsampling_force_desubsampling_inside_decompression==0) + { + if (q==0) + { + if (o!=((sp->subsampling_hor<<4)|sp->subsampling_ver)) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values"); + return(0); + } + } + else + { + if (o!=17) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values"); + return(0); + } + } + } + } + /* Tq: Quantization table destination selector */ + if (OJPEGReadByte(sp,&o)==0) + return(0); + if (sp->subsamplingcorrect==0) + sp->sof_tq[q]=o; + } + if (sp->subsamplingcorrect==0) + sp->sof_log=1; + return(1); } static int OJPEGReadHeaderInfoSecStreamSos(TIFF* tif) { - /* this marker needs to be checked, and part of its data needs to be saved for regeneration later on */ - static const char module[]="OJPEGReadHeaderInfoSecStreamSos"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint16 m; - uint8 n; - uint8 o; - assert(sp->subsamplingcorrect==0); - if (sp->sof_log==0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); - return(0); - } - /* Ls */ - if (OJPEGReadWord(sp,&m)==0) - return(0); - if (m!=6+sp->samples_per_pixel_per_plane*2) - { - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); - return(0); - } - /* Ns */ - if (OJPEGReadByte(sp,&n)==0) - return(0); - if (n!=sp->samples_per_pixel_per_plane) - { - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); - return(0); - } - /* Cs, Td, and Ta */ - for (o=0; osamples_per_pixel_per_plane; o++) - { - /* Cs */ - if (OJPEGReadByte(sp,&n)==0) - return(0); - sp->sos_cs[sp->plane_sample_offset+o]=n; - /* Td and Ta */ - if (OJPEGReadByte(sp,&n)==0) - return(0); - sp->sos_tda[sp->plane_sample_offset+o]=n; - } - /* skip Ss, Se, Ah, en Al -> no check, as per Tom Lane recommendation, as per LibJpeg source */ - OJPEGReadSkip(sp,3); - return(1); + /* this marker needs to be checked, and part of its data needs to be saved for regeneration later on */ + static const char module[]="OJPEGReadHeaderInfoSecStreamSos"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint16 m; + uint8 n; + uint8 o; + assert(sp->subsamplingcorrect==0); + if (sp->sof_log==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); + return(0); + } + /* Ls */ + if (OJPEGReadWord(sp,&m)==0) + return(0); + if (m!=6+sp->samples_per_pixel_per_plane*2) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); + return(0); + } + /* Ns */ + if (OJPEGReadByte(sp,&n)==0) + return(0); + if (n!=sp->samples_per_pixel_per_plane) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data"); + return(0); + } + /* Cs, Td, and Ta */ + for (o=0; osamples_per_pixel_per_plane; o++) + { + /* Cs */ + if (OJPEGReadByte(sp,&n)==0) + return(0); + sp->sos_cs[sp->plane_sample_offset+o]=n; + /* Td and Ta */ + if (OJPEGReadByte(sp,&n)==0) + return(0); + sp->sos_tda[sp->plane_sample_offset+o]=n; + } + /* skip Ss, Se, Ah, en Al -> no check, as per Tom Lane recommendation, as per LibJpeg source */ + OJPEGReadSkip(sp,3); + return(1); } static int OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif) { - static const char module[]="OJPEGReadHeaderInfoSecTablesQTable"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8 m; - uint8 n; - uint32 oa; - uint8* ob; - uint32 p; - if (sp->qtable_offset[0]==0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); - return(0); - } - sp->in_buffer_file_pos_log=0; - for (m=0; msamples_per_pixel; m++) - { - if ((sp->qtable_offset[m]!=0) && ((m==0) || (sp->qtable_offset[m]!=sp->qtable_offset[m-1]))) - { - for (n=0; nqtable_offset[m]==sp->qtable_offset[n]) - { - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegQTables tag value"); - return(0); - } - } - oa=sizeof(uint32)+69; - ob=_TIFFmalloc(oa); - if (ob==0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - *(uint32*)ob=oa; - ob[sizeof(uint32)]=255; - ob[sizeof(uint32)+1]=JPEG_MARKER_DQT; - ob[sizeof(uint32)+2]=0; - ob[sizeof(uint32)+3]=67; - ob[sizeof(uint32)+4]=m; - TIFFSeekFile(tif,sp->qtable_offset[m],SEEK_SET); - p=TIFFReadFile(tif,&ob[sizeof(uint32)+5],64); - if (p!=64) - return(0); - sp->qtable[m]=ob; - sp->sof_tq[m]=m; - } - else - sp->sof_tq[m]=sp->sof_tq[m-1]; - } - return(1); + static const char module[]="OJPEGReadHeaderInfoSecTablesQTable"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + uint8 n; + uint32 oa; + uint8* ob; + uint32 p; + if (sp->qtable_offset[0]==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); + return(0); + } + sp->in_buffer_file_pos_log=0; + for (m=0; msamples_per_pixel; m++) + { + if ((sp->qtable_offset[m]!=0) && ((m==0) || (sp->qtable_offset[m]!=sp->qtable_offset[m-1]))) + { + for (n=0; nqtable_offset[m]==sp->qtable_offset[n]) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegQTables tag value"); + return(0); + } + } + oa=sizeof(uint32)+69; + ob=_TIFFmalloc(oa); + if (ob==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + *(uint32*)ob=oa; + ob[sizeof(uint32)]=255; + ob[sizeof(uint32)+1]=JPEG_MARKER_DQT; + ob[sizeof(uint32)+2]=0; + ob[sizeof(uint32)+3]=67; + ob[sizeof(uint32)+4]=m; + TIFFSeekFile(tif,sp->qtable_offset[m],SEEK_SET); + p=(uint32)TIFFReadFile(tif,&ob[sizeof(uint32)+5],64); + if (p!=64) + { + _TIFFfree(ob); + return(0); + } + if (sp->qtable[m]!=0) + _TIFFfree(sp->qtable[m]); + sp->qtable[m]=ob; + sp->sof_tq[m]=m; + } + else + sp->sof_tq[m]=sp->sof_tq[m-1]; + } + return(1); } static int OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif) { - static const char module[]="OJPEGReadHeaderInfoSecTablesDcTable"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8 m; - uint8 n; - uint8 o[16]; - uint32 p; - uint32 q; - uint32 ra; - uint8* rb; - if (sp->dctable_offset[0]==0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); - return(0); - } - sp->in_buffer_file_pos_log=0; - for (m=0; msamples_per_pixel; m++) - { - if ((sp->dctable_offset[m]!=0) && ((m==0) || (sp->dctable_offset[m]!=sp->dctable_offset[m-1]))) - { - for (n=0; ndctable_offset[m]==sp->dctable_offset[n]) - { - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegDcTables tag value"); - return(0); - } - } - TIFFSeekFile(tif,sp->dctable_offset[m],SEEK_SET); - p=TIFFReadFile(tif,o,16); - if (p!=16) - return(0); - q=0; - for (n=0; n<16; n++) - q+=o[n]; - ra=sizeof(uint32)+21+q; - rb=_TIFFmalloc(ra); - if (rb==0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - *(uint32*)rb=ra; - rb[sizeof(uint32)]=255; - rb[sizeof(uint32)+1]=JPEG_MARKER_DHT; - rb[sizeof(uint32)+2]=((19+q)>>8); - rb[sizeof(uint32)+3]=((19+q)&255); - rb[sizeof(uint32)+4]=m; - for (n=0; n<16; n++) - rb[sizeof(uint32)+5+n]=o[n]; - p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); - if (p!=q) - return(0); - sp->dctable[m]=rb; - sp->sos_tda[m]=(m<<4); - } - else - sp->sos_tda[m]=sp->sos_tda[m-1]; - } - return(1); + static const char module[]="OJPEGReadHeaderInfoSecTablesDcTable"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + uint8 n; + uint8 o[16]; + uint32 p; + uint32 q; + uint32 ra; + uint8* rb; + if (sp->dctable_offset[0]==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); + return(0); + } + sp->in_buffer_file_pos_log=0; + for (m=0; msamples_per_pixel; m++) + { + if ((sp->dctable_offset[m]!=0) && ((m==0) || (sp->dctable_offset[m]!=sp->dctable_offset[m-1]))) + { + for (n=0; ndctable_offset[m]==sp->dctable_offset[n]) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegDcTables tag value"); + return(0); + } + } + TIFFSeekFile(tif,sp->dctable_offset[m],SEEK_SET); + p=(uint32)TIFFReadFile(tif,o,16); + if (p!=16) + return(0); + q=0; + for (n=0; n<16; n++) + q+=o[n]; + ra=sizeof(uint32)+21+q; + rb=_TIFFmalloc(ra); + if (rb==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + *(uint32*)rb=ra; + rb[sizeof(uint32)]=255; + rb[sizeof(uint32)+1]=JPEG_MARKER_DHT; + rb[sizeof(uint32)+2]=(uint8)((19+q)>>8); + rb[sizeof(uint32)+3]=((19+q)&255); + rb[sizeof(uint32)+4]=m; + for (n=0; n<16; n++) + rb[sizeof(uint32)+5+n]=o[n]; + p=(uint32)TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); + if (p!=q) + { + _TIFFfree(rb); + return(0); + } + if (sp->dctable[m]!=0) + _TIFFfree(sp->dctable[m]); + sp->dctable[m]=rb; + sp->sos_tda[m]=(m<<4); + } + else + sp->sos_tda[m]=sp->sos_tda[m-1]; + } + return(1); } static int OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif) { - static const char module[]="OJPEGReadHeaderInfoSecTablesAcTable"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8 m; - uint8 n; - uint8 o[16]; - uint32 p; - uint32 q; - uint32 ra; - uint8* rb; - if (sp->actable_offset[0]==0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); - return(0); - } - sp->in_buffer_file_pos_log=0; - for (m=0; msamples_per_pixel; m++) - { - if ((sp->actable_offset[m]!=0) && ((m==0) || (sp->actable_offset[m]!=sp->actable_offset[m-1]))) - { - for (n=0; nactable_offset[m]==sp->actable_offset[n]) - { - TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegAcTables tag value"); - return(0); - } - } - TIFFSeekFile(tif,sp->actable_offset[m],SEEK_SET); - p=TIFFReadFile(tif,o,16); - if (p!=16) - return(0); - q=0; - for (n=0; n<16; n++) - q+=o[n]; - ra=sizeof(uint32)+21+q; - rb=_TIFFmalloc(ra); - if (rb==0) - { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); - } - *(uint32*)rb=ra; - rb[sizeof(uint32)]=255; - rb[sizeof(uint32)+1]=JPEG_MARKER_DHT; - rb[sizeof(uint32)+2]=((19+q)>>8); - rb[sizeof(uint32)+3]=((19+q)&255); - rb[sizeof(uint32)+4]=(16|m); - for (n=0; n<16; n++) - rb[sizeof(uint32)+5+n]=o[n]; - p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); - if (p!=q) - return(0); - sp->actable[m]=rb; - sp->sos_tda[m]=(sp->sos_tda[m]|m); - } - else - sp->sos_tda[m]=(sp->sos_tda[m]|(sp->sos_tda[m-1]&15)); - } - return(1); + static const char module[]="OJPEGReadHeaderInfoSecTablesAcTable"; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + uint8 n; + uint8 o[16]; + uint32 p; + uint32 q; + uint32 ra; + uint8* rb; + if (sp->actable_offset[0]==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables"); + return(0); + } + sp->in_buffer_file_pos_log=0; + for (m=0; msamples_per_pixel; m++) + { + if ((sp->actable_offset[m]!=0) && ((m==0) || (sp->actable_offset[m]!=sp->actable_offset[m-1]))) + { + for (n=0; nactable_offset[m]==sp->actable_offset[n]) + { + TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegAcTables tag value"); + return(0); + } + } + TIFFSeekFile(tif,sp->actable_offset[m],SEEK_SET); + p=(uint32)TIFFReadFile(tif,o,16); + if (p!=16) + return(0); + q=0; + for (n=0; n<16; n++) + q+=o[n]; + ra=sizeof(uint32)+21+q; + rb=_TIFFmalloc(ra); + if (rb==0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + *(uint32*)rb=ra; + rb[sizeof(uint32)]=255; + rb[sizeof(uint32)+1]=JPEG_MARKER_DHT; + rb[sizeof(uint32)+2]=(uint8)((19+q)>>8); + rb[sizeof(uint32)+3]=((19+q)&255); + rb[sizeof(uint32)+4]=(16|m); + for (n=0; n<16; n++) + rb[sizeof(uint32)+5+n]=o[n]; + p=(uint32)TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q); + if (p!=q) + { + _TIFFfree(rb); + return(0); + } + if (sp->actable[m]!=0) + _TIFFfree(sp->actable[m]); + sp->actable[m]=rb; + sp->sos_tda[m]=(sp->sos_tda[m]|m); + } + else + sp->sos_tda[m]=(sp->sos_tda[m]|(sp->sos_tda[m-1]&15)); + } + return(1); } static int OJPEGReadBufferFill(OJPEGState* sp) { - uint16 m; - tmsize_t n; - /* TODO: double-check: when subsamplingcorrect is set, no call to TIFFErrorExt or TIFFWarningExt should be made - * in any other case, seek or read errors should be passed through */ - do - { - if (sp->in_buffer_file_togo!=0) - { - if (sp->in_buffer_file_pos_log==0) - { - TIFFSeekFile(sp->tif,sp->in_buffer_file_pos,SEEK_SET); - sp->in_buffer_file_pos_log=1; - } - m=OJPEG_BUFFER; - if ((uint64)m>sp->in_buffer_file_togo) - m=(uint16)sp->in_buffer_file_togo; - n=TIFFReadFile(sp->tif,sp->in_buffer,(tmsize_t)m); - if (n==0) - return(0); - assert(n>0); - assert(n<=OJPEG_BUFFER); - assert(n<65536); - assert((uint64)n<=sp->in_buffer_file_togo); - m=(uint16)n; - sp->in_buffer_togo=m; - sp->in_buffer_cur=sp->in_buffer; - sp->in_buffer_file_togo-=m; - sp->in_buffer_file_pos+=m; - break; - } - sp->in_buffer_file_pos_log=0; - switch(sp->in_buffer_source) - { - case osibsNotSetYet: - if (sp->jpeg_interchange_format!=0) - { - sp->in_buffer_file_pos=sp->jpeg_interchange_format; - sp->in_buffer_file_togo=sp->jpeg_interchange_format_length; - } - sp->in_buffer_source=osibsJpegInterchangeFormat; - break; - case osibsJpegInterchangeFormat: - sp->in_buffer_source=osibsStrile; - case osibsStrile: - if (!_TIFFFillStriles( sp->tif ) - || sp->tif->tif_dir.td_stripoffset == NULL - || sp->tif->tif_dir.td_stripbytecount == NULL) - return 0; + uint16 m; + tmsize_t n; + /* TODO: double-check: when subsamplingcorrect is set, no call to TIFFErrorExt or TIFFWarningExt should be made + * in any other case, seek or read errors should be passed through */ + do + { + if (sp->in_buffer_file_togo!=0) + { + if (sp->in_buffer_file_pos_log==0) + { + TIFFSeekFile(sp->tif,sp->in_buffer_file_pos,SEEK_SET); + sp->in_buffer_file_pos_log=1; + } + m=OJPEG_BUFFER; + if ((uint64)m>sp->in_buffer_file_togo) + m=(uint16)sp->in_buffer_file_togo; + n=TIFFReadFile(sp->tif,sp->in_buffer,(tmsize_t)m); + if (n==0) + return(0); + assert(n>0); + assert(n<=OJPEG_BUFFER); + assert(n<65536); + assert((uint64)n<=sp->in_buffer_file_togo); + m=(uint16)n; + sp->in_buffer_togo=m; + sp->in_buffer_cur=sp->in_buffer; + sp->in_buffer_file_togo-=m; + sp->in_buffer_file_pos+=m; + break; + } + sp->in_buffer_file_pos_log=0; + switch(sp->in_buffer_source) + { + case osibsNotSetYet: + if (sp->jpeg_interchange_format!=0) + { + sp->in_buffer_file_pos=sp->jpeg_interchange_format; + sp->in_buffer_file_togo=sp->jpeg_interchange_format_length; + } + sp->in_buffer_source=osibsJpegInterchangeFormat; + break; + case osibsJpegInterchangeFormat: + sp->in_buffer_source=osibsStrile; + break; + case osibsStrile: + if (!_TIFFFillStriles( sp->tif ) + || sp->tif->tif_dir.td_stripoffset == NULL + || sp->tif->tif_dir.td_stripbytecount == NULL) + return 0; - if (sp->in_buffer_next_strile==sp->in_buffer_strile_count) - sp->in_buffer_source=osibsEof; - else - { - sp->in_buffer_file_pos=sp->tif->tif_dir.td_stripoffset[sp->in_buffer_next_strile]; - if (sp->in_buffer_file_pos!=0) - { - if (sp->in_buffer_file_pos>=sp->file_size) - sp->in_buffer_file_pos=0; - else if (sp->tif->tif_dir.td_stripbytecount==NULL) - sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; - else - { - if (sp->tif->tif_dir.td_stripbytecount == 0) { - TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip byte counts are missing"); - return(0); - } - sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile]; - if (sp->in_buffer_file_togo==0) - sp->in_buffer_file_pos=0; - else if (sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size) - sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; - } - } - sp->in_buffer_next_strile++; - } - break; - default: - return(0); - } - } while (1); - return(1); + if (sp->in_buffer_next_strile==sp->in_buffer_strile_count) + sp->in_buffer_source=osibsEof; + else + { + sp->in_buffer_file_pos=sp->tif->tif_dir.td_stripoffset[sp->in_buffer_next_strile]; + if (sp->in_buffer_file_pos!=0) + { + if (sp->in_buffer_file_pos>=sp->file_size) + sp->in_buffer_file_pos=0; + else if (sp->tif->tif_dir.td_stripbytecount==NULL) + sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; + else + { + if (sp->tif->tif_dir.td_stripbytecount == 0) { + TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip byte counts are missing"); + return(0); + } + sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile]; + if (sp->in_buffer_file_togo==0) + sp->in_buffer_file_pos=0; + else if (sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size) + sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; + } + } + sp->in_buffer_next_strile++; + } + break; + default: + return(0); + } + } while (1); + return(1); } static int OJPEGReadByte(OJPEGState* sp, uint8* byte) { - if (sp->in_buffer_togo==0) - { - if (OJPEGReadBufferFill(sp)==0) - return(0); - assert(sp->in_buffer_togo>0); - } - *byte=*(sp->in_buffer_cur); - sp->in_buffer_cur++; - sp->in_buffer_togo--; - return(1); + if (sp->in_buffer_togo==0) + { + if (OJPEGReadBufferFill(sp)==0) + return(0); + assert(sp->in_buffer_togo>0); + } + *byte=*(sp->in_buffer_cur); + sp->in_buffer_cur++; + sp->in_buffer_togo--; + return(1); } static int OJPEGReadBytePeek(OJPEGState* sp, uint8* byte) { - if (sp->in_buffer_togo==0) - { - if (OJPEGReadBufferFill(sp)==0) - return(0); - assert(sp->in_buffer_togo>0); - } - *byte=*(sp->in_buffer_cur); - return(1); + if (sp->in_buffer_togo==0) + { + if (OJPEGReadBufferFill(sp)==0) + return(0); + assert(sp->in_buffer_togo>0); + } + *byte=*(sp->in_buffer_cur); + return(1); } static void OJPEGReadByteAdvance(OJPEGState* sp) { - assert(sp->in_buffer_togo>0); - sp->in_buffer_cur++; - sp->in_buffer_togo--; + assert(sp->in_buffer_togo>0); + sp->in_buffer_cur++; + sp->in_buffer_togo--; } static int OJPEGReadWord(OJPEGState* sp, uint16* word) { - uint8 m; - if (OJPEGReadByte(sp,&m)==0) - return(0); - *word=(m<<8); - if (OJPEGReadByte(sp,&m)==0) - return(0); - *word|=m; - return(1); + uint8 m; + if (OJPEGReadByte(sp,&m)==0) + return(0); + *word=(m<<8); + if (OJPEGReadByte(sp,&m)==0) + return(0); + *word|=m; + return(1); } static int OJPEGReadBlock(OJPEGState* sp, uint16 len, void* mem) { - uint16 mlen; - uint8* mmem; - uint16 n; - assert(len>0); - mlen=len; - mmem=mem; - do - { - if (sp->in_buffer_togo==0) - { - if (OJPEGReadBufferFill(sp)==0) - return(0); - assert(sp->in_buffer_togo>0); - } - n=mlen; - if (n>sp->in_buffer_togo) - n=sp->in_buffer_togo; - _TIFFmemcpy(mmem,sp->in_buffer_cur,n); - sp->in_buffer_cur+=n; - sp->in_buffer_togo-=n; - mlen-=n; - mmem+=n; - } while(mlen>0); - return(1); + uint16 mlen; + uint8* mmem; + uint16 n; + assert(len>0); + mlen=len; + mmem=mem; + do + { + if (sp->in_buffer_togo==0) + { + if (OJPEGReadBufferFill(sp)==0) + return(0); + assert(sp->in_buffer_togo>0); + } + n=mlen; + if (n>sp->in_buffer_togo) + n=sp->in_buffer_togo; + _TIFFmemcpy(mmem,sp->in_buffer_cur,n); + sp->in_buffer_cur+=n; + sp->in_buffer_togo-=n; + mlen-=n; + mmem+=n; + } while(mlen>0); + return(1); } static void OJPEGReadSkip(OJPEGState* sp, uint16 len) { - uint16 m; - uint16 n; - m=len; - n=m; - if (n>sp->in_buffer_togo) - n=sp->in_buffer_togo; - sp->in_buffer_cur+=n; - sp->in_buffer_togo-=n; - m-=n; - if (m>0) - { - assert(sp->in_buffer_togo==0); - n=m; - if ((uint64)n>sp->in_buffer_file_togo) - n=(uint16)sp->in_buffer_file_togo; - sp->in_buffer_file_pos+=n; - sp->in_buffer_file_togo-=n; - sp->in_buffer_file_pos_log=0; - /* we don't skip past jpeginterchangeformat/strile block... - * if that is asked from us, we're dealing with totally bazurk - * data anyway, and we've not seen this happening on any - * testfile, so we might as well likely cause some other - * meaningless error to be passed at some later time - */ - } + uint16 m; + uint16 n; + m=len; + n=m; + if (n>sp->in_buffer_togo) + n=sp->in_buffer_togo; + sp->in_buffer_cur+=n; + sp->in_buffer_togo-=n; + m-=n; + if (m>0) + { + assert(sp->in_buffer_togo==0); + n=m; + if ((uint64)n>sp->in_buffer_file_togo) + n=(uint16)sp->in_buffer_file_togo; + sp->in_buffer_file_pos+=n; + sp->in_buffer_file_togo-=n; + sp->in_buffer_file_pos_log=0; + /* we don't skip past jpeginterchangeformat/strile block... + * if that is asked from us, we're dealing with totally bazurk + * data anyway, and we've not seen this happening on any + * testfile, so we might as well likely cause some other + * meaningless error to be passed at some later time + */ + } } static int OJPEGWriteStream(TIFF* tif, void** mem, uint32* len) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - *len=0; - do - { - assert(sp->out_state<=ososEoi); - switch(sp->out_state) - { - case ososSoi: - OJPEGWriteStreamSoi(tif,mem,len); - break; - case ososQTable0: - OJPEGWriteStreamQTable(tif,0,mem,len); - break; - case ososQTable1: - OJPEGWriteStreamQTable(tif,1,mem,len); - break; - case ososQTable2: - OJPEGWriteStreamQTable(tif,2,mem,len); - break; - case ososQTable3: - OJPEGWriteStreamQTable(tif,3,mem,len); - break; - case ososDcTable0: - OJPEGWriteStreamDcTable(tif,0,mem,len); - break; - case ososDcTable1: - OJPEGWriteStreamDcTable(tif,1,mem,len); - break; - case ososDcTable2: - OJPEGWriteStreamDcTable(tif,2,mem,len); - break; - case ososDcTable3: - OJPEGWriteStreamDcTable(tif,3,mem,len); - break; - case ososAcTable0: - OJPEGWriteStreamAcTable(tif,0,mem,len); - break; - case ososAcTable1: - OJPEGWriteStreamAcTable(tif,1,mem,len); - break; - case ososAcTable2: - OJPEGWriteStreamAcTable(tif,2,mem,len); - break; - case ososAcTable3: - OJPEGWriteStreamAcTable(tif,3,mem,len); - break; - case ososDri: - OJPEGWriteStreamDri(tif,mem,len); - break; - case ososSof: - OJPEGWriteStreamSof(tif,mem,len); - break; - case ososSos: - OJPEGWriteStreamSos(tif,mem,len); - break; - case ososCompressed: - if (OJPEGWriteStreamCompressed(tif,mem,len)==0) - return(0); - break; - case ososRst: - OJPEGWriteStreamRst(tif,mem,len); - break; - case ososEoi: - OJPEGWriteStreamEoi(tif,mem,len); - break; - } - } while (*len==0); - return(1); + OJPEGState* sp=(OJPEGState*)tif->tif_data; + *len=0; + do + { + assert(sp->out_state<=ososEoi); + switch(sp->out_state) + { + case ososSoi: + OJPEGWriteStreamSoi(tif,mem,len); + break; + case ososQTable0: + OJPEGWriteStreamQTable(tif,0,mem,len); + break; + case ososQTable1: + OJPEGWriteStreamQTable(tif,1,mem,len); + break; + case ososQTable2: + OJPEGWriteStreamQTable(tif,2,mem,len); + break; + case ososQTable3: + OJPEGWriteStreamQTable(tif,3,mem,len); + break; + case ososDcTable0: + OJPEGWriteStreamDcTable(tif,0,mem,len); + break; + case ososDcTable1: + OJPEGWriteStreamDcTable(tif,1,mem,len); + break; + case ososDcTable2: + OJPEGWriteStreamDcTable(tif,2,mem,len); + break; + case ososDcTable3: + OJPEGWriteStreamDcTable(tif,3,mem,len); + break; + case ososAcTable0: + OJPEGWriteStreamAcTable(tif,0,mem,len); + break; + case ososAcTable1: + OJPEGWriteStreamAcTable(tif,1,mem,len); + break; + case ososAcTable2: + OJPEGWriteStreamAcTable(tif,2,mem,len); + break; + case ososAcTable3: + OJPEGWriteStreamAcTable(tif,3,mem,len); + break; + case ososDri: + OJPEGWriteStreamDri(tif,mem,len); + break; + case ososSof: + OJPEGWriteStreamSof(tif,mem,len); + break; + case ososSos: + OJPEGWriteStreamSos(tif,mem,len); + break; + case ososCompressed: + if (OJPEGWriteStreamCompressed(tif,mem,len)==0) + return(0); + break; + case ososRst: + OJPEGWriteStreamRst(tif,mem,len); + break; + case ososEoi: + OJPEGWriteStreamEoi(tif,mem,len); + break; + } + } while (*len==0); + return(1); } static void OJPEGWriteStreamSoi(TIFF* tif, void** mem, uint32* len) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - assert(OJPEG_BUFFER>=2); - sp->out_buffer[0]=255; - sp->out_buffer[1]=JPEG_MARKER_SOI; - *len=2; - *mem=(void*)sp->out_buffer; - sp->out_state++; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(OJPEG_BUFFER>=2); + sp->out_buffer[0]=255; + sp->out_buffer[1]=JPEG_MARKER_SOI; + *len=2; + *mem=(void*)sp->out_buffer; + sp->out_state++; } static void OJPEGWriteStreamQTable(TIFF* tif, uint8 table_index, void** mem, uint32* len) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - if (sp->qtable[table_index]!=0) - { - *mem=(void*)(sp->qtable[table_index]+sizeof(uint32)); - *len=*((uint32*)sp->qtable[table_index])-sizeof(uint32); - } - sp->out_state++; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + if (sp->qtable[table_index]!=0) + { + *mem=(void*)(sp->qtable[table_index]+sizeof(uint32)); + *len=*((uint32*)sp->qtable[table_index])-sizeof(uint32); + } + sp->out_state++; } static void OJPEGWriteStreamDcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - if (sp->dctable[table_index]!=0) - { - *mem=(void*)(sp->dctable[table_index]+sizeof(uint32)); - *len=*((uint32*)sp->dctable[table_index])-sizeof(uint32); - } - sp->out_state++; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + if (sp->dctable[table_index]!=0) + { + *mem=(void*)(sp->dctable[table_index]+sizeof(uint32)); + *len=*((uint32*)sp->dctable[table_index])-sizeof(uint32); + } + sp->out_state++; } static void OJPEGWriteStreamAcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - if (sp->actable[table_index]!=0) - { - *mem=(void*)(sp->actable[table_index]+sizeof(uint32)); - *len=*((uint32*)sp->actable[table_index])-sizeof(uint32); - } - sp->out_state++; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + if (sp->actable[table_index]!=0) + { + *mem=(void*)(sp->actable[table_index]+sizeof(uint32)); + *len=*((uint32*)sp->actable[table_index])-sizeof(uint32); + } + sp->out_state++; } static void OJPEGWriteStreamDri(TIFF* tif, void** mem, uint32* len) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - assert(OJPEG_BUFFER>=6); - if (sp->restart_interval!=0) - { - sp->out_buffer[0]=255; - sp->out_buffer[1]=JPEG_MARKER_DRI; - sp->out_buffer[2]=0; - sp->out_buffer[3]=4; - sp->out_buffer[4]=(sp->restart_interval>>8); - sp->out_buffer[5]=(sp->restart_interval&255); - *len=6; - *mem=(void*)sp->out_buffer; - } - sp->out_state++; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(OJPEG_BUFFER>=6); + if (sp->restart_interval!=0) + { + sp->out_buffer[0]=255; + sp->out_buffer[1]=JPEG_MARKER_DRI; + sp->out_buffer[2]=0; + sp->out_buffer[3]=4; + sp->out_buffer[4]=(sp->restart_interval>>8); + sp->out_buffer[5]=(sp->restart_interval&255); + *len=6; + *mem=(void*)sp->out_buffer; + } + sp->out_state++; } static void OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8 m; - assert(OJPEG_BUFFER>=2+8+sp->samples_per_pixel_per_plane*3); - assert(255>=8+sp->samples_per_pixel_per_plane*3); - sp->out_buffer[0]=255; - sp->out_buffer[1]=sp->sof_marker_id; - /* Lf */ - sp->out_buffer[2]=0; - sp->out_buffer[3]=8+sp->samples_per_pixel_per_plane*3; - /* P */ - sp->out_buffer[4]=8; - /* Y */ - sp->out_buffer[5]=(sp->sof_y>>8); - sp->out_buffer[6]=(sp->sof_y&255); - /* X */ - sp->out_buffer[7]=(sp->sof_x>>8); - sp->out_buffer[8]=(sp->sof_x&255); - /* Nf */ - sp->out_buffer[9]=sp->samples_per_pixel_per_plane; - for (m=0; msamples_per_pixel_per_plane; m++) - { - /* C */ - sp->out_buffer[10+m*3]=sp->sof_c[sp->plane_sample_offset+m]; - /* H and V */ - sp->out_buffer[10+m*3+1]=sp->sof_hv[sp->plane_sample_offset+m]; - /* Tq */ - sp->out_buffer[10+m*3+2]=sp->sof_tq[sp->plane_sample_offset+m]; - } - *len=10+sp->samples_per_pixel_per_plane*3; - *mem=(void*)sp->out_buffer; - sp->out_state++; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + assert(OJPEG_BUFFER>=2+8+sp->samples_per_pixel_per_plane*3); + assert(255>=8+sp->samples_per_pixel_per_plane*3); + sp->out_buffer[0]=255; + sp->out_buffer[1]=sp->sof_marker_id; + /* Lf */ + sp->out_buffer[2]=0; + sp->out_buffer[3]=8+sp->samples_per_pixel_per_plane*3; + /* P */ + sp->out_buffer[4]=8; + /* Y */ + sp->out_buffer[5]=(uint8)(sp->sof_y>>8); + sp->out_buffer[6]=(sp->sof_y&255); + /* X */ + sp->out_buffer[7]=(uint8)(sp->sof_x>>8); + sp->out_buffer[8]=(sp->sof_x&255); + /* Nf */ + sp->out_buffer[9]=sp->samples_per_pixel_per_plane; + for (m=0; msamples_per_pixel_per_plane; m++) + { + /* C */ + sp->out_buffer[10+m*3]=sp->sof_c[sp->plane_sample_offset+m]; + /* H and V */ + sp->out_buffer[10+m*3+1]=sp->sof_hv[sp->plane_sample_offset+m]; + /* Tq */ + sp->out_buffer[10+m*3+2]=sp->sof_tq[sp->plane_sample_offset+m]; + } + *len=10+sp->samples_per_pixel_per_plane*3; + *mem=(void*)sp->out_buffer; + sp->out_state++; } static void OJPEGWriteStreamSos(TIFF* tif, void** mem, uint32* len) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - uint8 m; - assert(OJPEG_BUFFER>=2+6+sp->samples_per_pixel_per_plane*2); - assert(255>=6+sp->samples_per_pixel_per_plane*2); - sp->out_buffer[0]=255; - sp->out_buffer[1]=JPEG_MARKER_SOS; - /* Ls */ - sp->out_buffer[2]=0; - sp->out_buffer[3]=6+sp->samples_per_pixel_per_plane*2; - /* Ns */ - sp->out_buffer[4]=sp->samples_per_pixel_per_plane; - for (m=0; msamples_per_pixel_per_plane; m++) - { - /* Cs */ - sp->out_buffer[5+m*2]=sp->sos_cs[sp->plane_sample_offset+m]; - /* Td and Ta */ - sp->out_buffer[5+m*2+1]=sp->sos_tda[sp->plane_sample_offset+m]; - } - /* Ss */ - sp->out_buffer[5+sp->samples_per_pixel_per_plane*2]=0; - /* Se */ - sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+1]=63; - /* Ah and Al */ - sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+2]=0; - *len=8+sp->samples_per_pixel_per_plane*2; - *mem=(void*)sp->out_buffer; - sp->out_state++; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + uint8 m; + assert(OJPEG_BUFFER>=2+6+sp->samples_per_pixel_per_plane*2); + assert(255>=6+sp->samples_per_pixel_per_plane*2); + sp->out_buffer[0]=255; + sp->out_buffer[1]=JPEG_MARKER_SOS; + /* Ls */ + sp->out_buffer[2]=0; + sp->out_buffer[3]=6+sp->samples_per_pixel_per_plane*2; + /* Ns */ + sp->out_buffer[4]=sp->samples_per_pixel_per_plane; + for (m=0; msamples_per_pixel_per_plane; m++) + { + /* Cs */ + sp->out_buffer[5+m*2]=sp->sos_cs[sp->plane_sample_offset+m]; + /* Td and Ta */ + sp->out_buffer[5+m*2+1]=sp->sos_tda[sp->plane_sample_offset+m]; + } + /* Ss */ + sp->out_buffer[5+sp->samples_per_pixel_per_plane*2]=0; + /* Se */ + sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+1]=63; + /* Ah and Al */ + sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+2]=0; + *len=8+sp->samples_per_pixel_per_plane*2; + *mem=(void*)sp->out_buffer; + sp->out_state++; } static int OJPEGWriteStreamCompressed(TIFF* tif, void** mem, uint32* len) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - if (sp->in_buffer_togo==0) - { - if (OJPEGReadBufferFill(sp)==0) - return(0); - assert(sp->in_buffer_togo>0); - } - *len=sp->in_buffer_togo; - *mem=(void*)sp->in_buffer_cur; - sp->in_buffer_togo=0; - if (sp->in_buffer_file_togo==0) - { - switch(sp->in_buffer_source) - { - case osibsStrile: - if (sp->in_buffer_next_strilein_buffer_strile_count) - sp->out_state=ososRst; - else - sp->out_state=ososEoi; - break; - case osibsEof: - sp->out_state=ososEoi; - break; - default: - break; - } - } - return(1); + OJPEGState* sp=(OJPEGState*)tif->tif_data; + if (sp->in_buffer_togo==0) + { + if (OJPEGReadBufferFill(sp)==0) + return(0); + assert(sp->in_buffer_togo>0); + } + *len=sp->in_buffer_togo; + *mem=(void*)sp->in_buffer_cur; + sp->in_buffer_togo=0; + if (sp->in_buffer_file_togo==0) + { + switch(sp->in_buffer_source) + { + case osibsStrile: + if (sp->in_buffer_next_strilein_buffer_strile_count) + sp->out_state=ososRst; + else + sp->out_state=ososEoi; + break; + case osibsEof: + sp->out_state=ososEoi; + break; + default: + break; + } + } + return(1); } static void OJPEGWriteStreamRst(TIFF* tif, void** mem, uint32* len) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - assert(OJPEG_BUFFER>=2); - sp->out_buffer[0]=255; - sp->out_buffer[1]=JPEG_MARKER_RST0+sp->restart_index; - sp->restart_index++; - if (sp->restart_index==8) - sp->restart_index=0; - *len=2; - *mem=(void*)sp->out_buffer; - sp->out_state=ososCompressed; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(OJPEG_BUFFER>=2); + sp->out_buffer[0]=255; + sp->out_buffer[1]=JPEG_MARKER_RST0+sp->restart_index; + sp->restart_index++; + if (sp->restart_index==8) + sp->restart_index=0; + *len=2; + *mem=(void*)sp->out_buffer; + sp->out_state=ososCompressed; } static void OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* len) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - assert(OJPEG_BUFFER>=2); - sp->out_buffer[0]=255; - sp->out_buffer[1]=JPEG_MARKER_EOI; - *len=2; - *mem=(void*)sp->out_buffer; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + assert(OJPEG_BUFFER>=2); + sp->out_buffer[0]=255; + sp->out_buffer[1]=JPEG_MARKER_EOI; + *len=2; + *mem=(void*)sp->out_buffer; } #ifndef LIBJPEG_ENCAP_EXTERNAL static int jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) { - return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_create_decompress(cinfo),1)); + if( SETJMP(sp->exit_jmpbuf) ) + return 0; + else { + jpeg_create_decompress(cinfo); + return 1; + } } #endif @@ -2382,7 +2422,12 @@ jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) static int jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image) { - return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_header(cinfo,require_image),1)); + if( SETJMP(sp->exit_jmpbuf) ) + return 0; + else { + jpeg_read_header(cinfo,require_image); + return 1; + } } #endif @@ -2390,7 +2435,12 @@ jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 requ static int jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) { - return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_start_decompress(cinfo),1)); + if( SETJMP(sp->exit_jmpbuf) ) + return 0; + else { + jpeg_start_decompress(cinfo); + return 1; + } } #endif @@ -2398,7 +2448,12 @@ jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo) static int jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines) { - return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_scanlines(cinfo,scanlines,max_lines),1)); + if( SETJMP(sp->exit_jmpbuf) ) + return 0; + else { + jpeg_read_scanlines(cinfo,scanlines,max_lines); + return 1; + } } #endif @@ -2406,7 +2461,12 @@ jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* s static int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines) { - return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_raw_data(cinfo,data,max_lines),1)); + if( SETJMP(sp->exit_jmpbuf) ) + return 0; + else { + jpeg_read_raw_data(cinfo,data,max_lines); + return 1; + } } #endif @@ -2414,74 +2474,81 @@ jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* da static void jpeg_encap_unwind(TIFF* tif) { - OJPEGState* sp=(OJPEGState*)tif->tif_data; - LONGJMP(sp->exit_jmpbuf,1); + OJPEGState* sp=(OJPEGState*)tif->tif_data; + LONGJMP(sp->exit_jmpbuf,1); } #endif static void OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct* cinfo) { - char buffer[JMSG_LENGTH_MAX]; - (*cinfo->err->format_message)(cinfo,buffer); - TIFFWarningExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg","%s",buffer); + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(cinfo,buffer); + TIFFWarningExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg","%s",buffer); } static void OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct* cinfo) { - char buffer[JMSG_LENGTH_MAX]; - (*cinfo->err->format_message)(cinfo,buffer); - TIFFErrorExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg","%s",buffer); - jpeg_encap_unwind((TIFF*)(cinfo->client_data)); + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(cinfo,buffer); + TIFFErrorExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg","%s",buffer); + jpeg_encap_unwind((TIFF*)(cinfo->client_data)); } static void OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct* cinfo) { - (void)cinfo; + (void)cinfo; } static boolean OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct* cinfo) { - TIFF* tif=(TIFF*)cinfo->client_data; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - void* mem=0; - uint32 len=0U; - if (OJPEGWriteStream(tif,&mem,&len)==0) - { - TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Premature end of JPEG data"); - jpeg_encap_unwind(tif); - } - sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=len; - sp->libjpeg_jpeg_source_mgr.next_input_byte=mem; - return(1); + TIFF* tif=(TIFF*)cinfo->client_data; + OJPEGState* sp=(OJPEGState*)tif->tif_data; + void* mem=0; + uint32 len=0U; + if (OJPEGWriteStream(tif,&mem,&len)==0) + { + TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Premature end of JPEG data"); + jpeg_encap_unwind(tif); + } + sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=len; + sp->libjpeg_jpeg_source_mgr.next_input_byte=mem; + return(1); } static void OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct* cinfo, long num_bytes) { - TIFF* tif=(TIFF*)cinfo->client_data; - (void)num_bytes; - TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error"); - jpeg_encap_unwind(tif); + TIFF* tif=(TIFF*)cinfo->client_data; + (void)num_bytes; + TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error"); + jpeg_encap_unwind(tif); } +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4702 ) /* unreachable code */ +#endif static boolean OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired) { - TIFF* tif=(TIFF*)cinfo->client_data; - (void)desired; - TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error"); - jpeg_encap_unwind(tif); - return(0); + TIFF* tif=(TIFF*)cinfo->client_data; + (void)desired; + TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error"); + jpeg_encap_unwind(tif); + return(0); } +#ifdef _MSC_VER +#pragma warning( pop ) +#endif static void OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo) { - (void)cinfo; + (void)cinfo; } #endif diff --git a/3rdparty/libtiff/tif_open.c b/3rdparty/libtiff/tif_open.c index 8a18f5c341..a7279e1ea0 100644 --- a/3rdparty/libtiff/tif_open.c +++ b/3rdparty/libtiff/tif_open.c @@ -1,26 +1,26 @@ -/* $Id: tif_open.c,v 1.46 2010-12-06 16:54:54 faxguy Exp $ */ +/* $Id: tif_open.c,v 1.48 2016-11-20 22:29:47 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -35,455 +35,455 @@ static int _tiffDummyMapProc(thandle_t fd, void** pbase, toff_t* psize) { - (void) fd; (void) pbase; (void) psize; - return (0); + (void) fd; (void) pbase; (void) psize; + return (0); } static void _tiffDummyUnmapProc(thandle_t fd, void* base, toff_t size) { - (void) fd; (void) base; (void) size; + (void) fd; (void) base; (void) size; } int _TIFFgetMode(const char* mode, const char* module) { - int m = -1; + int m = -1; - switch (mode[0]) { - case 'r': - m = O_RDONLY; - if (mode[1] == '+') - m = O_RDWR; - break; - case 'w': - case 'a': - m = O_RDWR|O_CREAT; - if (mode[0] == 'w') - m |= O_TRUNC; - break; - default: - TIFFErrorExt(0, module, "\"%s\": Bad mode", mode); - break; - } - return (m); + switch (mode[0]) { + case 'r': + m = O_RDONLY; + if (mode[1] == '+') + m = O_RDWR; + break; + case 'w': + case 'a': + m = O_RDWR|O_CREAT; + if (mode[0] == 'w') + m |= O_TRUNC; + break; + default: + TIFFErrorExt(0, module, "\"%s\": Bad mode", mode); + break; + } + return (m); } TIFF* TIFFClientOpen( - const char* name, const char* mode, - thandle_t clientdata, - TIFFReadWriteProc readproc, - TIFFReadWriteProc writeproc, - TIFFSeekProc seekproc, - TIFFCloseProc closeproc, - TIFFSizeProc sizeproc, - TIFFMapFileProc mapproc, - TIFFUnmapFileProc unmapproc + const char* name, const char* mode, + thandle_t clientdata, + TIFFReadWriteProc readproc, + TIFFReadWriteProc writeproc, + TIFFSeekProc seekproc, + TIFFCloseProc closeproc, + TIFFSizeProc sizeproc, + TIFFMapFileProc mapproc, + TIFFUnmapFileProc unmapproc ) { - static const char module[] = "TIFFClientOpen"; - TIFF *tif; - int m; - const char* cp; + static const char module[] = "TIFFClientOpen"; + TIFF *tif; + int m; + const char* cp; - /* The following are configuration checks. They should be redundant, but should not - * compile to any actual code in an optimised release build anyway. If any of them - * fail, (makefile-based or other) configuration is not correct */ - assert(sizeof(uint8)==1); - assert(sizeof(int8)==1); - assert(sizeof(uint16)==2); - assert(sizeof(int16)==2); - assert(sizeof(uint32)==4); - assert(sizeof(int32)==4); - assert(sizeof(uint64)==8); - assert(sizeof(int64)==8); - assert(sizeof(tmsize_t)==sizeof(void*)); - { - union{ - uint8 a8[2]; - uint16 a16; - } n; - n.a8[0]=1; - n.a8[1]=0; - #ifdef WORDS_BIGENDIAN - assert(n.a16==256); - #else - assert(n.a16==1); - #endif - } + /* The following are configuration checks. They should be redundant, but should not + * compile to any actual code in an optimised release build anyway. If any of them + * fail, (makefile-based or other) configuration is not correct */ + assert(sizeof(uint8)==1); + assert(sizeof(int8)==1); + assert(sizeof(uint16)==2); + assert(sizeof(int16)==2); + assert(sizeof(uint32)==4); + assert(sizeof(int32)==4); + assert(sizeof(uint64)==8); + assert(sizeof(int64)==8); + assert(sizeof(tmsize_t)==sizeof(void*)); + { + union{ + uint8 a8[2]; + uint16 a16; + } n; + n.a8[0]=1; + n.a8[1]=0; + #ifdef WORDS_BIGENDIAN + assert(n.a16==256); + #else + assert(n.a16==1); + #endif + } - m = _TIFFgetMode(mode, module); - if (m == -1) - goto bad2; - tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1)); - if (tif == NULL) { - TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name); - goto bad2; - } - _TIFFmemset(tif, 0, sizeof (*tif)); - tif->tif_name = (char *)tif + sizeof (TIFF); - strcpy(tif->tif_name, name); - tif->tif_mode = m &~ (O_CREAT|O_TRUNC); - tif->tif_curdir = (uint16) -1; /* non-existent directory */ - tif->tif_curoff = 0; - tif->tif_curstrip = (uint32) -1; /* invalid strip */ - tif->tif_row = (uint32) -1; /* read/write pre-increment */ - tif->tif_clientdata = clientdata; - if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) { - TIFFErrorExt(clientdata, module, - "One of the client procedures is NULL pointer."); - goto bad2; - } - tif->tif_readproc = readproc; - tif->tif_writeproc = writeproc; - tif->tif_seekproc = seekproc; - tif->tif_closeproc = closeproc; - tif->tif_sizeproc = sizeproc; - if (mapproc) - tif->tif_mapproc = mapproc; - else - tif->tif_mapproc = _tiffDummyMapProc; - if (unmapproc) - tif->tif_unmapproc = unmapproc; - else - tif->tif_unmapproc = _tiffDummyUnmapProc; - _TIFFSetDefaultCompressionState(tif); /* setup default state */ - /* - * Default is to return data MSB2LSB and enable the - * use of memory-mapped files and strip chopping when - * a file is opened read-only. - */ - tif->tif_flags = FILLORDER_MSB2LSB; - if (m == O_RDONLY ) - tif->tif_flags |= TIFF_MAPPED; + m = _TIFFgetMode(mode, module); + if (m == -1) + goto bad2; + tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1)); + if (tif == NULL) { + TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name); + goto bad2; + } + _TIFFmemset(tif, 0, sizeof (*tif)); + tif->tif_name = (char *)tif + sizeof (TIFF); + strcpy(tif->tif_name, name); + tif->tif_mode = m &~ (O_CREAT|O_TRUNC); + tif->tif_curdir = (uint16) -1; /* non-existent directory */ + tif->tif_curoff = 0; + tif->tif_curstrip = (uint32) -1; /* invalid strip */ + tif->tif_row = (uint32) -1; /* read/write pre-increment */ + tif->tif_clientdata = clientdata; + if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) { + TIFFErrorExt(clientdata, module, + "One of the client procedures is NULL pointer."); + goto bad2; + } + tif->tif_readproc = readproc; + tif->tif_writeproc = writeproc; + tif->tif_seekproc = seekproc; + tif->tif_closeproc = closeproc; + tif->tif_sizeproc = sizeproc; + if (mapproc) + tif->tif_mapproc = mapproc; + else + tif->tif_mapproc = _tiffDummyMapProc; + if (unmapproc) + tif->tif_unmapproc = unmapproc; + else + tif->tif_unmapproc = _tiffDummyUnmapProc; + _TIFFSetDefaultCompressionState(tif); /* setup default state */ + /* + * Default is to return data MSB2LSB and enable the + * use of memory-mapped files and strip chopping when + * a file is opened read-only. + */ + tif->tif_flags = FILLORDER_MSB2LSB; + if (m == O_RDONLY ) + tif->tif_flags |= TIFF_MAPPED; - #ifdef STRIPCHOP_DEFAULT - if (m == O_RDONLY || m == O_RDWR) - tif->tif_flags |= STRIPCHOP_DEFAULT; - #endif + #ifdef STRIPCHOP_DEFAULT + if (m == O_RDONLY || m == O_RDWR) + tif->tif_flags |= STRIPCHOP_DEFAULT; + #endif - /* - * Process library-specific flags in the open mode string. - * The following flags may be used to control intrinsic library - * behaviour that may or may not be desirable (usually for - * compatibility with some application that claims to support - * TIFF but only supports some braindead idea of what the - * vendor thinks TIFF is): - * - * 'l' use little-endian byte order for creating a file - * 'b' use big-endian byte order for creating a file - * 'L' read/write information using LSB2MSB bit order - * 'B' read/write information using MSB2LSB bit order - * 'H' read/write information using host bit order - * 'M' enable use of memory-mapped files when supported - * 'm' disable use of memory-mapped files - * 'C' enable strip chopping support when reading - * 'c' disable strip chopping support - * 'h' read TIFF header only, do not load the first IFD - * '4' ClassicTIFF for creating a file (default) - * '8' BigTIFF for creating a file - * - * The use of the 'l' and 'b' flags is strongly discouraged. - * These flags are provided solely because numerous vendors, - * typically on the PC, do not correctly support TIFF; they - * only support the Intel little-endian byte order. This - * support is not configured by default because it supports - * the violation of the TIFF spec that says that readers *MUST* - * support both byte orders. It is strongly recommended that - * you not use this feature except to deal with busted apps - * that write invalid TIFF. And even in those cases you should - * bang on the vendors to fix their software. - * - * The 'L', 'B', and 'H' flags are intended for applications - * that can optimize operations on data by using a particular - * bit order. By default the library returns data in MSB2LSB - * bit order for compatibiltiy with older versions of this - * library. Returning data in the bit order of the native cpu - * makes the most sense but also requires applications to check - * the value of the FillOrder tag; something they probably do - * not do right now. - * - * The 'M' and 'm' flags are provided because some virtual memory - * systems exhibit poor behaviour when large images are mapped. - * These options permit clients to control the use of memory-mapped - * files on a per-file basis. - * - * The 'C' and 'c' flags are provided because the library support - * for chopping up large strips into multiple smaller strips is not - * application-transparent and as such can cause problems. The 'c' - * option permits applications that only want to look at the tags, - * for example, to get the unadulterated TIFF tag information. - */ - for (cp = mode; *cp; cp++) - switch (*cp) { - case 'b': - #ifndef WORDS_BIGENDIAN - if (m&O_CREAT) - tif->tif_flags |= TIFF_SWAB; - #endif - break; - case 'l': - #ifdef WORDS_BIGENDIAN - if ((m&O_CREAT)) - tif->tif_flags |= TIFF_SWAB; - #endif - break; - case 'B': - tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | - FILLORDER_MSB2LSB; - break; - case 'L': - tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | - FILLORDER_LSB2MSB; - break; - case 'H': - tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | - HOST_FILLORDER; - break; - case 'M': - if (m == O_RDONLY) - tif->tif_flags |= TIFF_MAPPED; - break; - case 'm': - if (m == O_RDONLY) - tif->tif_flags &= ~TIFF_MAPPED; - break; - case 'C': - if (m == O_RDONLY) - tif->tif_flags |= TIFF_STRIPCHOP; - break; - case 'c': - if (m == O_RDONLY) - tif->tif_flags &= ~TIFF_STRIPCHOP; - break; - case 'h': - tif->tif_flags |= TIFF_HEADERONLY; - break; - case '8': - if (m&O_CREAT) - tif->tif_flags |= TIFF_BIGTIFF; - break; - } - /* - * Read in TIFF header. - */ - if ((m & O_TRUNC) || - !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeaderClassic))) { - if (tif->tif_mode == O_RDONLY) { - TIFFErrorExt(tif->tif_clientdata, name, - "Cannot read TIFF header"); - goto bad; - } - /* - * Setup header and write. - */ - #ifdef WORDS_BIGENDIAN - tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB - ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN; - #else - tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB - ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN; - #endif - if (!(tif->tif_flags&TIFF_BIGTIFF)) - { - tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC; - tif->tif_header.classic.tiff_diroff = 0; - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabShort(&tif->tif_header.common.tiff_version); - tif->tif_header_size = sizeof(TIFFHeaderClassic); - } - else - { - tif->tif_header.common.tiff_version = TIFF_VERSION_BIG; - tif->tif_header.big.tiff_offsetsize = 8; - tif->tif_header.big.tiff_unused = 0; - tif->tif_header.big.tiff_diroff = 0; - if (tif->tif_flags & TIFF_SWAB) - { - TIFFSwabShort(&tif->tif_header.common.tiff_version); - TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize); - } - tif->tif_header_size = sizeof (TIFFHeaderBig); - } - /* - * The doc for "fopen" for some STD_C_LIBs says that if you - * open a file for modify ("+"), then you must fseek (or - * fflush?) between any freads and fwrites. This is not - * necessary on most systems, but has been shown to be needed - * on Solaris. - */ - TIFFSeekFile( tif, 0, SEEK_SET ); - if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size))) { - TIFFErrorExt(tif->tif_clientdata, name, - "Error writing TIFF header"); - goto bad; - } - /* - * Setup the byte order handling. - */ - if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) { - #ifndef WORDS_BIGENDIAN - tif->tif_flags |= TIFF_SWAB; - #endif - } else { - #ifdef WORDS_BIGENDIAN - tif->tif_flags |= TIFF_SWAB; - #endif - } - /* - * Setup default directory. - */ - if (!TIFFDefaultDirectory(tif)) - goto bad; - tif->tif_diroff = 0; - tif->tif_dirlist = NULL; - tif->tif_dirlistsize = 0; - tif->tif_dirnumber = 0; - return (tif); - } - /* - * Setup the byte order handling. - */ - if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN && - tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN - #if MDI_SUPPORT - && - #if HOST_BIGENDIAN - tif->tif_header.common.tiff_magic != MDI_BIGENDIAN - #else - tif->tif_header.common.tiff_magic != MDI_LITTLEENDIAN - #endif - ) { - TIFFErrorExt(tif->tif_clientdata, name, - "Not a TIFF or MDI file, bad magic number %d (0x%x)", - #else - ) { - TIFFErrorExt(tif->tif_clientdata, name, - "Not a TIFF file, bad magic number %d (0x%x)", - #endif - tif->tif_header.common.tiff_magic, - tif->tif_header.common.tiff_magic); - goto bad; - } - if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) { - #ifndef WORDS_BIGENDIAN - tif->tif_flags |= TIFF_SWAB; - #endif - } else { - #ifdef WORDS_BIGENDIAN - tif->tif_flags |= TIFF_SWAB; - #endif - } - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabShort(&tif->tif_header.common.tiff_version); - if ((tif->tif_header.common.tiff_version != TIFF_VERSION_CLASSIC)&& - (tif->tif_header.common.tiff_version != TIFF_VERSION_BIG)) { - TIFFErrorExt(tif->tif_clientdata, name, - "Not a TIFF file, bad version number %d (0x%x)", - tif->tif_header.common.tiff_version, - tif->tif_header.common.tiff_version); - goto bad; - } - if (tif->tif_header.common.tiff_version == TIFF_VERSION_CLASSIC) - { - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong(&tif->tif_header.classic.tiff_diroff); - tif->tif_header_size = sizeof(TIFFHeaderClassic); - } - else - { - if (!ReadOK(tif, ((uint8*)(&tif->tif_header) + sizeof(TIFFHeaderClassic)), (sizeof(TIFFHeaderBig)-sizeof(TIFFHeaderClassic)))) - { - TIFFErrorExt(tif->tif_clientdata, name, - "Cannot read TIFF header"); - goto bad; - } - if (tif->tif_flags & TIFF_SWAB) - { - TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize); - TIFFSwabLong8(&tif->tif_header.big.tiff_diroff); - } - if (tif->tif_header.big.tiff_offsetsize != 8) - { - TIFFErrorExt(tif->tif_clientdata, name, - "Not a TIFF file, bad BigTIFF offsetsize %d (0x%x)", - tif->tif_header.big.tiff_offsetsize, - tif->tif_header.big.tiff_offsetsize); - goto bad; - } - if (tif->tif_header.big.tiff_unused != 0) - { - TIFFErrorExt(tif->tif_clientdata, name, - "Not a TIFF file, bad BigTIFF unused %d (0x%x)", - tif->tif_header.big.tiff_unused, - tif->tif_header.big.tiff_unused); - goto bad; - } - tif->tif_header_size = sizeof(TIFFHeaderBig); - tif->tif_flags |= TIFF_BIGTIFF; - } - tif->tif_flags |= TIFF_MYBUFFER; - tif->tif_rawcp = tif->tif_rawdata = 0; - tif->tif_rawdatasize = 0; + /* + * Process library-specific flags in the open mode string. + * The following flags may be used to control intrinsic library + * behaviour that may or may not be desirable (usually for + * compatibility with some application that claims to support + * TIFF but only supports some brain dead idea of what the + * vendor thinks TIFF is): + * + * 'l' use little-endian byte order for creating a file + * 'b' use big-endian byte order for creating a file + * 'L' read/write information using LSB2MSB bit order + * 'B' read/write information using MSB2LSB bit order + * 'H' read/write information using host bit order + * 'M' enable use of memory-mapped files when supported + * 'm' disable use of memory-mapped files + * 'C' enable strip chopping support when reading + * 'c' disable strip chopping support + * 'h' read TIFF header only, do not load the first IFD + * '4' ClassicTIFF for creating a file (default) + * '8' BigTIFF for creating a file + * + * The use of the 'l' and 'b' flags is strongly discouraged. + * These flags are provided solely because numerous vendors, + * typically on the PC, do not correctly support TIFF; they + * only support the Intel little-endian byte order. This + * support is not configured by default because it supports + * the violation of the TIFF spec that says that readers *MUST* + * support both byte orders. It is strongly recommended that + * you not use this feature except to deal with busted apps + * that write invalid TIFF. And even in those cases you should + * bang on the vendors to fix their software. + * + * The 'L', 'B', and 'H' flags are intended for applications + * that can optimize operations on data by using a particular + * bit order. By default the library returns data in MSB2LSB + * bit order for compatibility with older versions of this + * library. Returning data in the bit order of the native CPU + * makes the most sense but also requires applications to check + * the value of the FillOrder tag; something they probably do + * not do right now. + * + * The 'M' and 'm' flags are provided because some virtual memory + * systems exhibit poor behaviour when large images are mapped. + * These options permit clients to control the use of memory-mapped + * files on a per-file basis. + * + * The 'C' and 'c' flags are provided because the library support + * for chopping up large strips into multiple smaller strips is not + * application-transparent and as such can cause problems. The 'c' + * option permits applications that only want to look at the tags, + * for example, to get the unadulterated TIFF tag information. + */ + for (cp = mode; *cp; cp++) + switch (*cp) { + case 'b': + #ifndef WORDS_BIGENDIAN + if (m&O_CREAT) + tif->tif_flags |= TIFF_SWAB; + #endif + break; + case 'l': + #ifdef WORDS_BIGENDIAN + if ((m&O_CREAT)) + tif->tif_flags |= TIFF_SWAB; + #endif + break; + case 'B': + tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | + FILLORDER_MSB2LSB; + break; + case 'L': + tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | + FILLORDER_LSB2MSB; + break; + case 'H': + tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) | + HOST_FILLORDER; + break; + case 'M': + if (m == O_RDONLY) + tif->tif_flags |= TIFF_MAPPED; + break; + case 'm': + if (m == O_RDONLY) + tif->tif_flags &= ~TIFF_MAPPED; + break; + case 'C': + if (m == O_RDONLY) + tif->tif_flags |= TIFF_STRIPCHOP; + break; + case 'c': + if (m == O_RDONLY) + tif->tif_flags &= ~TIFF_STRIPCHOP; + break; + case 'h': + tif->tif_flags |= TIFF_HEADERONLY; + break; + case '8': + if (m&O_CREAT) + tif->tif_flags |= TIFF_BIGTIFF; + break; + } + /* + * Read in TIFF header. + */ + if ((m & O_TRUNC) || + !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeaderClassic))) { + if (tif->tif_mode == O_RDONLY) { + TIFFErrorExt(tif->tif_clientdata, name, + "Cannot read TIFF header"); + goto bad; + } + /* + * Setup header and write. + */ + #ifdef WORDS_BIGENDIAN + tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB) + ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN; + #else + tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB) + ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN; + #endif + if (!(tif->tif_flags&TIFF_BIGTIFF)) + { + tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC; + tif->tif_header.classic.tiff_diroff = 0; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&tif->tif_header.common.tiff_version); + tif->tif_header_size = sizeof(TIFFHeaderClassic); + } + else + { + tif->tif_header.common.tiff_version = TIFF_VERSION_BIG; + tif->tif_header.big.tiff_offsetsize = 8; + tif->tif_header.big.tiff_unused = 0; + tif->tif_header.big.tiff_diroff = 0; + if (tif->tif_flags & TIFF_SWAB) + { + TIFFSwabShort(&tif->tif_header.common.tiff_version); + TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize); + } + tif->tif_header_size = sizeof (TIFFHeaderBig); + } + /* + * The doc for "fopen" for some STD_C_LIBs says that if you + * open a file for modify ("+"), then you must fseek (or + * fflush?) between any freads and fwrites. This is not + * necessary on most systems, but has been shown to be needed + * on Solaris. + */ + TIFFSeekFile( tif, 0, SEEK_SET ); + if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size))) { + TIFFErrorExt(tif->tif_clientdata, name, + "Error writing TIFF header"); + goto bad; + } + /* + * Setup the byte order handling. + */ + if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) { + #ifndef WORDS_BIGENDIAN + tif->tif_flags |= TIFF_SWAB; + #endif + } else { + #ifdef WORDS_BIGENDIAN + tif->tif_flags |= TIFF_SWAB; + #endif + } + /* + * Setup default directory. + */ + if (!TIFFDefaultDirectory(tif)) + goto bad; + tif->tif_diroff = 0; + tif->tif_dirlist = NULL; + tif->tif_dirlistsize = 0; + tif->tif_dirnumber = 0; + return (tif); + } + /* + * Setup the byte order handling. + */ + if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN && + tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN + #if MDI_SUPPORT + && + #if HOST_BIGENDIAN + tif->tif_header.common.tiff_magic != MDI_BIGENDIAN + #else + tif->tif_header.common.tiff_magic != MDI_LITTLEENDIAN + #endif + ) { + TIFFErrorExt(tif->tif_clientdata, name, + "Not a TIFF or MDI file, bad magic number %d (0x%x)", + #else + ) { + TIFFErrorExt(tif->tif_clientdata, name, + "Not a TIFF file, bad magic number %d (0x%x)", + #endif + tif->tif_header.common.tiff_magic, + tif->tif_header.common.tiff_magic); + goto bad; + } + if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) { + #ifndef WORDS_BIGENDIAN + tif->tif_flags |= TIFF_SWAB; + #endif + } else { + #ifdef WORDS_BIGENDIAN + tif->tif_flags |= TIFF_SWAB; + #endif + } + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&tif->tif_header.common.tiff_version); + if ((tif->tif_header.common.tiff_version != TIFF_VERSION_CLASSIC)&& + (tif->tif_header.common.tiff_version != TIFF_VERSION_BIG)) { + TIFFErrorExt(tif->tif_clientdata, name, + "Not a TIFF file, bad version number %d (0x%x)", + tif->tif_header.common.tiff_version, + tif->tif_header.common.tiff_version); + goto bad; + } + if (tif->tif_header.common.tiff_version == TIFF_VERSION_CLASSIC) + { + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&tif->tif_header.classic.tiff_diroff); + tif->tif_header_size = sizeof(TIFFHeaderClassic); + } + else + { + if (!ReadOK(tif, ((uint8*)(&tif->tif_header) + sizeof(TIFFHeaderClassic)), (sizeof(TIFFHeaderBig)-sizeof(TIFFHeaderClassic)))) + { + TIFFErrorExt(tif->tif_clientdata, name, + "Cannot read TIFF header"); + goto bad; + } + if (tif->tif_flags & TIFF_SWAB) + { + TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize); + TIFFSwabLong8(&tif->tif_header.big.tiff_diroff); + } + if (tif->tif_header.big.tiff_offsetsize != 8) + { + TIFFErrorExt(tif->tif_clientdata, name, + "Not a TIFF file, bad BigTIFF offsetsize %d (0x%x)", + tif->tif_header.big.tiff_offsetsize, + tif->tif_header.big.tiff_offsetsize); + goto bad; + } + if (tif->tif_header.big.tiff_unused != 0) + { + TIFFErrorExt(tif->tif_clientdata, name, + "Not a TIFF file, bad BigTIFF unused %d (0x%x)", + tif->tif_header.big.tiff_unused, + tif->tif_header.big.tiff_unused); + goto bad; + } + tif->tif_header_size = sizeof(TIFFHeaderBig); + tif->tif_flags |= TIFF_BIGTIFF; + } + tif->tif_flags |= TIFF_MYBUFFER; + tif->tif_rawcp = tif->tif_rawdata = 0; + tif->tif_rawdatasize = 0; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = 0; - switch (mode[0]) { - case 'r': - if (!(tif->tif_flags&TIFF_BIGTIFF)) - tif->tif_nextdiroff = tif->tif_header.classic.tiff_diroff; - else - tif->tif_nextdiroff = tif->tif_header.big.tiff_diroff; - /* - * Try to use a memory-mapped file if the client - * has not explicitly suppressed usage with the - * 'm' flag in the open mode (see above). - */ - if (tif->tif_flags & TIFF_MAPPED) - { - toff_t n; - if (TIFFMapFileContents(tif,(void**)(&tif->tif_base),&n)) - { - tif->tif_size=(tmsize_t)n; - assert((toff_t)tif->tif_size==n); - } - else - tif->tif_flags &= ~TIFF_MAPPED; - } - /* - * Sometimes we do not want to read the first directory (for example, - * it may be broken) and want to proceed to other directories. I this - * case we use the TIFF_HEADERONLY flag to open file and return - * immediately after reading TIFF header. - */ - if (tif->tif_flags & TIFF_HEADERONLY) - return (tif); + switch (mode[0]) { + case 'r': + if (!(tif->tif_flags&TIFF_BIGTIFF)) + tif->tif_nextdiroff = tif->tif_header.classic.tiff_diroff; + else + tif->tif_nextdiroff = tif->tif_header.big.tiff_diroff; + /* + * Try to use a memory-mapped file if the client + * has not explicitly suppressed usage with the + * 'm' flag in the open mode (see above). + */ + if (tif->tif_flags & TIFF_MAPPED) + { + toff_t n; + if (TIFFMapFileContents(tif,(void**)(&tif->tif_base),&n)) + { + tif->tif_size=(tmsize_t)n; + assert((toff_t)tif->tif_size==n); + } + else + tif->tif_flags &= ~TIFF_MAPPED; + } + /* + * Sometimes we do not want to read the first directory (for example, + * it may be broken) and want to proceed to other directories. I this + * case we use the TIFF_HEADERONLY flag to open file and return + * immediately after reading TIFF header. + */ + if (tif->tif_flags & TIFF_HEADERONLY) + return (tif); - /* - * Setup initial directory. - */ - if (TIFFReadDirectory(tif)) { - tif->tif_rawcc = (tmsize_t)-1; - tif->tif_flags |= TIFF_BUFFERSETUP; - return (tif); - } - break; - case 'a': - /* - * New directories are automatically append - * to the end of the directory chain when they - * are written out (see TIFFWriteDirectory). - */ - if (!TIFFDefaultDirectory(tif)) - goto bad; - return (tif); - } + /* + * Setup initial directory. + */ + if (TIFFReadDirectory(tif)) { + tif->tif_rawcc = (tmsize_t)-1; + tif->tif_flags |= TIFF_BUFFERSETUP; + return (tif); + } + break; + case 'a': + /* + * New directories are automatically append + * to the end of the directory chain when they + * are written out (see TIFFWriteDirectory). + */ + if (!TIFFDefaultDirectory(tif)) + goto bad; + return (tif); + } bad: - tif->tif_mode = O_RDONLY; /* XXX avoid flush */ + tif->tif_mode = O_RDONLY; /* XXX avoid flush */ TIFFCleanup(tif); bad2: - return ((TIFF*)0); + return ((TIFF*)0); } /* @@ -496,7 +496,7 @@ bad2: const char * TIFFFileName(TIFF* tif) { - return (tif->tif_name); + return (tif->tif_name); } /* @@ -505,9 +505,9 @@ TIFFFileName(TIFF* tif) const char * TIFFSetFileName(TIFF* tif, const char *name) { - const char* old_name = tif->tif_name; - tif->tif_name = (char *)name; - return (old_name); + const char* old_name = tif->tif_name; + tif->tif_name = (char *)name; + return (old_name); } /* @@ -516,7 +516,7 @@ TIFFSetFileName(TIFF* tif, const char *name) int TIFFFileno(TIFF* tif) { - return (tif->tif_fd); + return (tif->tif_fd); } /* @@ -526,8 +526,8 @@ int TIFFSetFileno(TIFF* tif, int fd) { int old_fd = tif->tif_fd; - tif->tif_fd = fd; - return old_fd; + tif->tif_fd = fd; + return old_fd; } /* @@ -536,7 +536,7 @@ TIFFSetFileno(TIFF* tif, int fd) thandle_t TIFFClientdata(TIFF* tif) { - return (tif->tif_clientdata); + return (tif->tif_clientdata); } /* @@ -545,9 +545,9 @@ TIFFClientdata(TIFF* tif) thandle_t TIFFSetClientdata(TIFF* tif, thandle_t newvalue) { - thandle_t m = tif->tif_clientdata; - tif->tif_clientdata = newvalue; - return m; + thandle_t m = tif->tif_clientdata; + tif->tif_clientdata = newvalue; + return m; } /* @@ -556,7 +556,7 @@ TIFFSetClientdata(TIFF* tif, thandle_t newvalue) int TIFFGetMode(TIFF* tif) { - return (tif->tif_mode); + return (tif->tif_mode); } /* @@ -565,9 +565,9 @@ TIFFGetMode(TIFF* tif) int TIFFSetMode(TIFF* tif, int mode) { - int old_mode = tif->tif_mode; - tif->tif_mode = mode; - return (old_mode); + int old_mode = tif->tif_mode; + tif->tif_mode = mode; + return (old_mode); } /* @@ -577,7 +577,7 @@ TIFFSetMode(TIFF* tif, int mode) int TIFFIsTiled(TIFF* tif) { - return (isTiled(tif)); + return (isTiled(tif)); } /* @@ -586,7 +586,7 @@ TIFFIsTiled(TIFF* tif) uint32 TIFFCurrentRow(TIFF* tif) { - return (tif->tif_row); + return (tif->tif_row); } /* @@ -595,7 +595,7 @@ TIFFCurrentRow(TIFF* tif) uint16 TIFFCurrentDirectory(TIFF* tif) { - return (tif->tif_curdir); + return (tif->tif_curdir); } /* @@ -604,7 +604,7 @@ TIFFCurrentDirectory(TIFF* tif) uint32 TIFFCurrentStrip(TIFF* tif) { - return (tif->tif_curstrip); + return (tif->tif_curstrip); } /* @@ -613,7 +613,7 @@ TIFFCurrentStrip(TIFF* tif) uint32 TIFFCurrentTile(TIFF* tif) { - return (tif->tif_curtile); + return (tif->tif_curtile); } /* @@ -622,7 +622,7 @@ TIFFCurrentTile(TIFF* tif) int TIFFIsByteSwapped(TIFF* tif) { - return ((tif->tif_flags & TIFF_SWAB) != 0); + return ((tif->tif_flags & TIFF_SWAB) != 0); } /* @@ -631,7 +631,7 @@ TIFFIsByteSwapped(TIFF* tif) int TIFFIsUpSampled(TIFF* tif) { - return (isUpSampled(tif)); + return (isUpSampled(tif)); } /* @@ -640,7 +640,7 @@ TIFFIsUpSampled(TIFF* tif) int TIFFIsMSB2LSB(TIFF* tif) { - return (isFillOrder(tif, FILLORDER_MSB2LSB)); + return (isFillOrder(tif, FILLORDER_MSB2LSB)); } /* @@ -649,7 +649,7 @@ TIFFIsMSB2LSB(TIFF* tif) int TIFFIsBigEndian(TIFF* tif) { - return (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN); + return (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN); } /* @@ -658,7 +658,7 @@ TIFFIsBigEndian(TIFF* tif) TIFFReadWriteProc TIFFGetReadProc(TIFF* tif) { - return (tif->tif_readproc); + return (tif->tif_readproc); } /* @@ -667,7 +667,7 @@ TIFFGetReadProc(TIFF* tif) TIFFReadWriteProc TIFFGetWriteProc(TIFF* tif) { - return (tif->tif_writeproc); + return (tif->tif_writeproc); } /* @@ -676,7 +676,7 @@ TIFFGetWriteProc(TIFF* tif) TIFFSeekProc TIFFGetSeekProc(TIFF* tif) { - return (tif->tif_seekproc); + return (tif->tif_seekproc); } /* @@ -685,7 +685,7 @@ TIFFGetSeekProc(TIFF* tif) TIFFCloseProc TIFFGetCloseProc(TIFF* tif) { - return (tif->tif_closeproc); + return (tif->tif_closeproc); } /* @@ -694,7 +694,7 @@ TIFFGetCloseProc(TIFF* tif) TIFFSizeProc TIFFGetSizeProc(TIFF* tif) { - return (tif->tif_sizeproc); + return (tif->tif_sizeproc); } /* @@ -703,7 +703,7 @@ TIFFGetSizeProc(TIFF* tif) TIFFMapFileProc TIFFGetMapFileProc(TIFF* tif) { - return (tif->tif_mapproc); + return (tif->tif_mapproc); } /* @@ -712,7 +712,7 @@ TIFFGetMapFileProc(TIFF* tif) TIFFUnmapFileProc TIFFGetUnmapFileProc(TIFF* tif) { - return (tif->tif_unmapproc); + return (tif->tif_unmapproc); } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_packbits.c b/3rdparty/libtiff/tif_packbits.c index 8d3bd054c4..18904b0137 100644 --- a/3rdparty/libtiff/tif_packbits.c +++ b/3rdparty/libtiff/tif_packbits.c @@ -1,26 +1,26 @@ -/* $Id: tif_packbits.c,v 1.20 2010-03-10 18:56:49 bfriesen Exp $ */ +/* $Id: tif_packbits.c,v 1.26 2017-05-14 02:26:07 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -36,18 +36,19 @@ static int PackBitsPreEncode(TIFF* tif, uint16 s) { - (void) s; + (void) s; - if (!(tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t)))) - return (0); - /* - * Calculate the scanline/tile-width size in bytes. - */ - if (isTiled(tif)) - *(tmsize_t*)tif->tif_data = TIFFTileRowSize(tif); - else - *(tmsize_t*)tif->tif_data = TIFFScanlineSize(tif); - return (1); + tif->tif_data = (uint8*)_TIFFmalloc(sizeof(tmsize_t)); + if (tif->tif_data == NULL) + return (0); + /* + * Calculate the scanline/tile-width size in bytes. + */ + if (isTiled(tif)) + *(tmsize_t*)tif->tif_data = TIFFTileRowSize(tif); + else + *(tmsize_t*)tif->tif_data = TIFFScanlineSize(tif); + return (1); } static int @@ -55,7 +56,7 @@ PackBitsPostEncode(TIFF* tif) { if (tif->tif_data) _TIFFfree(tif->tif_data); - return (1); + return (1); } /* @@ -64,123 +65,125 @@ PackBitsPostEncode(TIFF* tif) static int PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) { - unsigned char* bp = (unsigned char*) buf; - uint8* op; - uint8* ep; - uint8* lastliteral; - long n, slop; - int b; - enum { BASE, LITERAL, RUN, LITERAL_RUN } state; + unsigned char* bp = (unsigned char*) buf; + uint8* op; + uint8* ep; + uint8* lastliteral; + long n, slop; + int b; + enum { BASE, LITERAL, RUN, LITERAL_RUN } state; - (void) s; - op = tif->tif_rawcp; - ep = tif->tif_rawdata + tif->tif_rawdatasize; - state = BASE; - lastliteral = 0; - while (cc > 0) { - /* - * Find the longest string of identical bytes. - */ - b = *bp++, cc--, n = 1; - for (; cc > 0 && b == *bp; cc--, bp++) - n++; - again: - if (op + 2 >= ep) { /* insure space for new data */ - /* - * Be careful about writing the last - * literal. Must write up to that point - * and then copy the remainder to the - * front of the buffer. - */ - if (state == LITERAL || state == LITERAL_RUN) { - slop = (long)(op - lastliteral); - tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp); - if (!TIFFFlushData1(tif)) - return (-1); - op = tif->tif_rawcp; - while (slop-- > 0) - *op++ = *lastliteral++; - lastliteral = tif->tif_rawcp; - } else { - tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp); - if (!TIFFFlushData1(tif)) - return (-1); - op = tif->tif_rawcp; - } - } - switch (state) { - case BASE: /* initial state, set run/literal */ - if (n > 1) { - state = RUN; - if (n > 128) { - *op++ = (uint8) -127; - *op++ = (uint8) b; - n -= 128; - goto again; - } - *op++ = (uint8)(-(n-1)); - *op++ = (uint8) b; - } else { - lastliteral = op; - *op++ = 0; - *op++ = (uint8) b; - state = LITERAL; - } - break; - case LITERAL: /* last object was literal string */ - if (n > 1) { - state = LITERAL_RUN; - if (n > 128) { - *op++ = (uint8) -127; - *op++ = (uint8) b; - n -= 128; - goto again; - } - *op++ = (uint8)(-(n-1)); /* encode run */ - *op++ = (uint8) b; - } else { /* extend literal */ - if (++(*lastliteral) == 127) - state = BASE; - *op++ = (uint8) b; - } - break; - case RUN: /* last object was run */ - if (n > 1) { - if (n > 128) { - *op++ = (uint8) -127; - *op++ = (uint8) b; - n -= 128; - goto again; - } - *op++ = (uint8)(-(n-1)); - *op++ = (uint8) b; - } else { - lastliteral = op; - *op++ = 0; - *op++ = (uint8) b; - state = LITERAL; - } - break; - case LITERAL_RUN: /* literal followed by a run */ - /* - * Check to see if previous run should - * be converted to a literal, in which - * case we convert literal-run-literal - * to a single literal. - */ - if (n == 1 && op[-2] == (uint8) -1 && - *lastliteral < 126) { - state = (((*lastliteral) += 2) == 127 ? - BASE : LITERAL); - op[-2] = op[-1]; /* replicate */ - } else - state = RUN; - goto again; - } - } - tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp); - tif->tif_rawcp = op; - return (1); + (void) s; + op = tif->tif_rawcp; + ep = tif->tif_rawdata + tif->tif_rawdatasize; + state = BASE; + lastliteral = 0; + while (cc > 0) { + /* + * Find the longest string of identical bytes. + */ + b = *bp++; + cc--; + n = 1; + for (; cc > 0 && b == *bp; cc--, bp++) + n++; + again: + if (op + 2 >= ep) { /* insure space for new data */ + /* + * Be careful about writing the last + * literal. Must write up to that point + * and then copy the remainder to the + * front of the buffer. + */ + if (state == LITERAL || state == LITERAL_RUN) { + slop = (long)(op - lastliteral); + tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp); + if (!TIFFFlushData1(tif)) + return (0); + op = tif->tif_rawcp; + while (slop-- > 0) + *op++ = *lastliteral++; + lastliteral = tif->tif_rawcp; + } else { + tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp); + if (!TIFFFlushData1(tif)) + return (0); + op = tif->tif_rawcp; + } + } + switch (state) { + case BASE: /* initial state, set run/literal */ + if (n > 1) { + state = RUN; + if (n > 128) { + *op++ = (uint8) -127; + *op++ = (uint8) b; + n -= 128; + goto again; + } + *op++ = (uint8)(-(n-1)); + *op++ = (uint8) b; + } else { + lastliteral = op; + *op++ = 0; + *op++ = (uint8) b; + state = LITERAL; + } + break; + case LITERAL: /* last object was literal string */ + if (n > 1) { + state = LITERAL_RUN; + if (n > 128) { + *op++ = (uint8) -127; + *op++ = (uint8) b; + n -= 128; + goto again; + } + *op++ = (uint8)(-(n-1)); /* encode run */ + *op++ = (uint8) b; + } else { /* extend literal */ + if (++(*lastliteral) == 127) + state = BASE; + *op++ = (uint8) b; + } + break; + case RUN: /* last object was run */ + if (n > 1) { + if (n > 128) { + *op++ = (uint8) -127; + *op++ = (uint8) b; + n -= 128; + goto again; + } + *op++ = (uint8)(-(n-1)); + *op++ = (uint8) b; + } else { + lastliteral = op; + *op++ = 0; + *op++ = (uint8) b; + state = LITERAL; + } + break; + case LITERAL_RUN: /* literal followed by a run */ + /* + * Check to see if previous run should + * be converted to a literal, in which + * case we convert literal-run-literal + * to a single literal. + */ + if (n == 1 && op[-2] == (uint8) -1 && + *lastliteral < 126) { + state = (((*lastliteral) += 2) == 127 ? + BASE : LITERAL); + op[-2] = op[-1]; /* replicate */ + } else + state = RUN; + goto again; + } + } + tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp); + tif->tif_rawcp = op; + return (1); } /* @@ -193,94 +196,108 @@ PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) static int PackBitsEncodeChunk(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - tmsize_t rowsize = *(tmsize_t*)tif->tif_data; + tmsize_t rowsize = *(tmsize_t*)tif->tif_data; - while (cc > 0) { - tmsize_t chunk = rowsize; + while (cc > 0) { + tmsize_t chunk = rowsize; + + if( cc < chunk ) + chunk = cc; - if( cc < chunk ) - chunk = cc; - - if (PackBitsEncode(tif, bp, chunk, s) < 0) - return (-1); - bp += chunk; - cc -= chunk; - } - return (1); + if (PackBitsEncode(tif, bp, chunk, s) < 0) + return (-1); + bp += chunk; + cc -= chunk; + } + return (1); } static int PackBitsDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) { - static const char module[] = "PackBitsDecode"; - char *bp; - tmsize_t cc; - long n; - int b; + static const char module[] = "PackBitsDecode"; + char *bp; + tmsize_t cc; + long n; + int b; - (void) s; - bp = (char*) tif->tif_rawcp; - cc = tif->tif_rawcc; - while (cc > 0 && occ > 0) { - n = (long) *bp++, cc--; - /* - * Watch out for compilers that - * don't sign extend chars... - */ - if (n >= 128) - n -= 256; - if (n < 0) { /* replicate next byte -n+1 times */ - if (n == -128) /* nop */ - continue; - n = -n + 1; - if( occ < (tmsize_t)n ) - { - TIFFWarningExt(tif->tif_clientdata, module, - "Discarding %lu bytes to avoid buffer overrun", - (unsigned long) ((tmsize_t)n - occ)); - n = (long)occ; - } - occ -= n; - b = *bp++, cc--; /* TODO: may be reading past input buffer here when input data is corrupt or ends prematurely */ - while (n-- > 0) - *op++ = (uint8) b; - } else { /* copy next n+1 bytes literally */ - if (occ < (tmsize_t)(n + 1)) - { - TIFFWarningExt(tif->tif_clientdata, module, - "Discarding %lu bytes to avoid buffer overrun", - (unsigned long) ((tmsize_t)n - occ + 1)); - n = (long)occ - 1; - } - _TIFFmemcpy(op, bp, ++n); /* TODO: may be reading past input buffer here when input data is corrupt or ends prematurely */ - op += n; occ -= n; - bp += n; cc -= n; - } - } - tif->tif_rawcp = (uint8*) bp; - tif->tif_rawcc = cc; - if (occ > 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data for scanline %lu", - (unsigned long) tif->tif_row); - return (0); - } - return (1); + (void) s; + bp = (char*) tif->tif_rawcp; + cc = tif->tif_rawcc; + while (cc > 0 && occ > 0) { + n = (long) *bp++; + cc--; + /* + * Watch out for compilers that + * don't sign extend chars... + */ + if (n >= 128) + n -= 256; + if (n < 0) { /* replicate next byte -n+1 times */ + if (n == -128) /* nop */ + continue; + n = -n + 1; + if( occ < (tmsize_t)n ) + { + TIFFWarningExt(tif->tif_clientdata, module, + "Discarding %lu bytes to avoid buffer overrun", + (unsigned long) ((tmsize_t)n - occ)); + n = (long)occ; + } + if( cc == 0 ) + { + TIFFWarningExt(tif->tif_clientdata, module, + "Terminating PackBitsDecode due to lack of data."); + break; + } + occ -= n; + b = *bp++; + cc--; + while (n-- > 0) + *op++ = (uint8) b; + } else { /* copy next n+1 bytes literally */ + if (occ < (tmsize_t)(n + 1)) + { + TIFFWarningExt(tif->tif_clientdata, module, + "Discarding %lu bytes to avoid buffer overrun", + (unsigned long) ((tmsize_t)n - occ + 1)); + n = (long)occ - 1; + } + if (cc < (tmsize_t) (n+1)) + { + TIFFWarningExt(tif->tif_clientdata, module, + "Terminating PackBitsDecode due to lack of data."); + break; + } + _TIFFmemcpy(op, bp, ++n); + op += n; occ -= n; + bp += n; cc -= n; + } + } + tif->tif_rawcp = (uint8*) bp; + tif->tif_rawcc = cc; + if (occ > 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data for scanline %lu", + (unsigned long) tif->tif_row); + return (0); + } + return (1); } int TIFFInitPackBits(TIFF* tif, int scheme) { - (void) scheme; - tif->tif_decoderow = PackBitsDecode; - tif->tif_decodestrip = PackBitsDecode; - tif->tif_decodetile = PackBitsDecode; - tif->tif_preencode = PackBitsPreEncode; - tif->tif_postencode = PackBitsPostEncode; - tif->tif_encoderow = PackBitsEncode; - tif->tif_encodestrip = PackBitsEncodeChunk; - tif->tif_encodetile = PackBitsEncodeChunk; - return (1); + (void) scheme; + tif->tif_decoderow = PackBitsDecode; + tif->tif_decodestrip = PackBitsDecode; + tif->tif_decodetile = PackBitsDecode; + tif->tif_preencode = PackBitsPreEncode; + tif->tif_postencode = PackBitsPostEncode; + tif->tif_encoderow = PackBitsEncode; + tif->tif_encodestrip = PackBitsEncodeChunk; + tif->tif_encodetile = PackBitsEncodeChunk; + return (1); } #endif /* PACKBITS_SUPPORT */ diff --git a/3rdparty/libtiff/tif_pixarlog.c b/3rdparty/libtiff/tif_pixarlog.c index 14b2772b0e..979858da9c 100644 --- a/3rdparty/libtiff/tif_pixarlog.c +++ b/3rdparty/libtiff/tif_pixarlog.c @@ -1,26 +1,26 @@ -/* $Id: tif_pixarlog.c,v 1.37 2012-05-24 23:21:45 fwarmerdam Exp $ */ +/* $Id: tif_pixarlog.c,v 1.54 2017-07-10 10:40:28 erouault Exp $ */ /* * Copyright (c) 1996-1997 Sam Leffler * Copyright (c) 1996 Pixar * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Pixar, Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL PIXAR, SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -34,10 +34,10 @@ * Contributed by Dan McCoy. * * PixarLog film support uses the TIFF library to store companded - * 11 bit values into a tiff file, which are compressed using the - * zip compressor. + * 11 bit values into a tiff file, which are compressed using the + * zip compressor. * - * The codec can take as input and produce as output 32-bit IEEE float values + * The codec can take as input and produce as output 32-bit IEEE float values * as well as 16-bit or 8-bit unsigned integer values. * * On writing any of the above are converted into the internal @@ -45,15 +45,15 @@ * input is assumed to be unsigned linear color values that represent * the range 0-1. In the case of IEEE values, the 0-1 range is assumed to * be the normal linear color range, in addition over 1 values are - * accepted up to a value of about 25.0 to encode "hot" hightlights and such. + * accepted up to a value of about 25.0 to encode "hot" highlights and such. * The encoding is lossless for 8-bit values, slightly lossy for the * other bit depths. The actual color precision should be better * than the human eye can perceive with extra room to allow for * error introduced by further image computation. As with any quantized * color format, it is possible to perform image calculations which - * expose the quantization error. This format should certainly be less - * susceptable to such errors than standard 8-bit encodings, but more - * susceptable than straight 16-bit or 32-bit encodings. + * expose the quantization error. This format should certainly be less + * susceptible to such errors than standard 8-bit encodings, but more + * susceptible than straight 16-bit or 32-bit encodings. * * On reading the internal format is converted to the desired output format. * The program can request which format it desires by setting the internal @@ -112,70 +112,70 @@ static float LogK1, LogK2; static void horizontalAccumulateF(uint16 *wp, int n, int stride, float *op, - float *ToLinearF) + float *ToLinearF) { register unsigned int cr, cg, cb, ca, mask; register float t0, t1, t2, t3; if (n >= stride) { - mask = CODE_MASK; - if (stride == 3) { - t0 = ToLinearF[cr = (wp[0] & mask)]; - t1 = ToLinearF[cg = (wp[1] & mask)]; - t2 = ToLinearF[cb = (wp[2] & mask)]; - op[0] = t0; - op[1] = t1; - op[2] = t2; - n -= 3; - while (n > 0) { - wp += 3; - op += 3; - n -= 3; - t0 = ToLinearF[(cr += wp[0]) & mask]; - t1 = ToLinearF[(cg += wp[1]) & mask]; - t2 = ToLinearF[(cb += wp[2]) & mask]; - op[0] = t0; - op[1] = t1; - op[2] = t2; - } - } else if (stride == 4) { - t0 = ToLinearF[cr = (wp[0] & mask)]; - t1 = ToLinearF[cg = (wp[1] & mask)]; - t2 = ToLinearF[cb = (wp[2] & mask)]; - t3 = ToLinearF[ca = (wp[3] & mask)]; - op[0] = t0; - op[1] = t1; - op[2] = t2; - op[3] = t3; - n -= 4; - while (n > 0) { - wp += 4; - op += 4; - n -= 4; - t0 = ToLinearF[(cr += wp[0]) & mask]; - t1 = ToLinearF[(cg += wp[1]) & mask]; - t2 = ToLinearF[(cb += wp[2]) & mask]; - t3 = ToLinearF[(ca += wp[3]) & mask]; - op[0] = t0; - op[1] = t1; - op[2] = t2; - op[3] = t3; - } - } else { - REPEAT(stride, *op = ToLinearF[*wp&mask]; wp++; op++) - n -= stride; - while (n > 0) { - REPEAT(stride, - wp[stride] += *wp; *op = ToLinearF[*wp&mask]; wp++; op++) - n -= stride; - } - } + mask = CODE_MASK; + if (stride == 3) { + t0 = ToLinearF[cr = (wp[0] & mask)]; + t1 = ToLinearF[cg = (wp[1] & mask)]; + t2 = ToLinearF[cb = (wp[2] & mask)]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + t0 = ToLinearF[(cr += wp[0]) & mask]; + t1 = ToLinearF[(cg += wp[1]) & mask]; + t2 = ToLinearF[(cb += wp[2]) & mask]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + } + } else if (stride == 4) { + t0 = ToLinearF[cr = (wp[0] & mask)]; + t1 = ToLinearF[cg = (wp[1] & mask)]; + t2 = ToLinearF[cb = (wp[2] & mask)]; + t3 = ToLinearF[ca = (wp[3] & mask)]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + t0 = ToLinearF[(cr += wp[0]) & mask]; + t1 = ToLinearF[(cg += wp[1]) & mask]; + t2 = ToLinearF[(cb += wp[2]) & mask]; + t3 = ToLinearF[(ca += wp[3]) & mask]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + } + } else { + REPEAT(stride, *op = ToLinearF[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinearF[*wp&mask]; wp++; op++) + n -= stride; + } + } } } static void horizontalAccumulate12(uint16 *wp, int n, int stride, int16 *op, - float *ToLinearF) + float *ToLinearF) { register unsigned int cr, cg, cb, ca, mask; register float t0, t1, t2, t3; @@ -184,269 +184,271 @@ horizontalAccumulate12(uint16 *wp, int n, int stride, int16 *op, #define CLAMP12(t) (((t) < 3071) ? (uint16) (t) : 3071) if (n >= stride) { - mask = CODE_MASK; - if (stride == 3) { - t0 = ToLinearF[cr = (wp[0] & mask)] * SCALE12; - t1 = ToLinearF[cg = (wp[1] & mask)] * SCALE12; - t2 = ToLinearF[cb = (wp[2] & mask)] * SCALE12; - op[0] = CLAMP12(t0); - op[1] = CLAMP12(t1); - op[2] = CLAMP12(t2); - n -= 3; - while (n > 0) { - wp += 3; - op += 3; - n -= 3; - t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12; - t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12; - t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12; - op[0] = CLAMP12(t0); - op[1] = CLAMP12(t1); - op[2] = CLAMP12(t2); - } - } else if (stride == 4) { - t0 = ToLinearF[cr = (wp[0] & mask)] * SCALE12; - t1 = ToLinearF[cg = (wp[1] & mask)] * SCALE12; - t2 = ToLinearF[cb = (wp[2] & mask)] * SCALE12; - t3 = ToLinearF[ca = (wp[3] & mask)] * SCALE12; - op[0] = CLAMP12(t0); - op[1] = CLAMP12(t1); - op[2] = CLAMP12(t2); - op[3] = CLAMP12(t3); - n -= 4; - while (n > 0) { - wp += 4; - op += 4; - n -= 4; - t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12; - t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12; - t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12; - t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12; - op[0] = CLAMP12(t0); - op[1] = CLAMP12(t1); - op[2] = CLAMP12(t2); - op[3] = CLAMP12(t3); - } - } else { - REPEAT(stride, t0 = ToLinearF[*wp&mask] * SCALE12; + mask = CODE_MASK; + if (stride == 3) { + t0 = ToLinearF[cr = (wp[0] & mask)] * SCALE12; + t1 = ToLinearF[cg = (wp[1] & mask)] * SCALE12; + t2 = ToLinearF[cb = (wp[2] & mask)] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12; + t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12; + t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + } + } else if (stride == 4) { + t0 = ToLinearF[cr = (wp[0] & mask)] * SCALE12; + t1 = ToLinearF[cg = (wp[1] & mask)] * SCALE12; + t2 = ToLinearF[cb = (wp[2] & mask)] * SCALE12; + t3 = ToLinearF[ca = (wp[3] & mask)] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + op[3] = CLAMP12(t3); + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12; + t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12; + t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12; + t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12; + op[0] = CLAMP12(t0); + op[1] = CLAMP12(t1); + op[2] = CLAMP12(t2); + op[3] = CLAMP12(t3); + } + } else { + REPEAT(stride, t0 = ToLinearF[*wp&mask] * SCALE12; *op = CLAMP12(t0); wp++; op++) - n -= stride; - while (n > 0) { - REPEAT(stride, - wp[stride] += *wp; t0 = ToLinearF[wp[stride]&mask]*SCALE12; - *op = CLAMP12(t0); wp++; op++) - n -= stride; - } - } + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; t0 = ToLinearF[wp[stride]&mask]*SCALE12; + *op = CLAMP12(t0); wp++; op++) + n -= stride; + } + } } } static void horizontalAccumulate16(uint16 *wp, int n, int stride, uint16 *op, - uint16 *ToLinear16) + uint16 *ToLinear16) { register unsigned int cr, cg, cb, ca, mask; if (n >= stride) { - mask = CODE_MASK; - if (stride == 3) { - op[0] = ToLinear16[cr = (wp[0] & mask)]; - op[1] = ToLinear16[cg = (wp[1] & mask)]; - op[2] = ToLinear16[cb = (wp[2] & mask)]; - n -= 3; - while (n > 0) { - wp += 3; - op += 3; - n -= 3; - op[0] = ToLinear16[(cr += wp[0]) & mask]; - op[1] = ToLinear16[(cg += wp[1]) & mask]; - op[2] = ToLinear16[(cb += wp[2]) & mask]; - } - } else if (stride == 4) { - op[0] = ToLinear16[cr = (wp[0] & mask)]; - op[1] = ToLinear16[cg = (wp[1] & mask)]; - op[2] = ToLinear16[cb = (wp[2] & mask)]; - op[3] = ToLinear16[ca = (wp[3] & mask)]; - n -= 4; - while (n > 0) { - wp += 4; - op += 4; - n -= 4; - op[0] = ToLinear16[(cr += wp[0]) & mask]; - op[1] = ToLinear16[(cg += wp[1]) & mask]; - op[2] = ToLinear16[(cb += wp[2]) & mask]; - op[3] = ToLinear16[(ca += wp[3]) & mask]; - } - } else { - REPEAT(stride, *op = ToLinear16[*wp&mask]; wp++; op++) - n -= stride; - while (n > 0) { - REPEAT(stride, - wp[stride] += *wp; *op = ToLinear16[*wp&mask]; wp++; op++) - n -= stride; - } - } + mask = CODE_MASK; + if (stride == 3) { + op[0] = ToLinear16[cr = (wp[0] & mask)]; + op[1] = ToLinear16[cg = (wp[1] & mask)]; + op[2] = ToLinear16[cb = (wp[2] & mask)]; + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + op[0] = ToLinear16[(cr += wp[0]) & mask]; + op[1] = ToLinear16[(cg += wp[1]) & mask]; + op[2] = ToLinear16[(cb += wp[2]) & mask]; + } + } else if (stride == 4) { + op[0] = ToLinear16[cr = (wp[0] & mask)]; + op[1] = ToLinear16[cg = (wp[1] & mask)]; + op[2] = ToLinear16[cb = (wp[2] & mask)]; + op[3] = ToLinear16[ca = (wp[3] & mask)]; + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + op[0] = ToLinear16[(cr += wp[0]) & mask]; + op[1] = ToLinear16[(cg += wp[1]) & mask]; + op[2] = ToLinear16[(cb += wp[2]) & mask]; + op[3] = ToLinear16[(ca += wp[3]) & mask]; + } + } else { + REPEAT(stride, *op = ToLinear16[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinear16[*wp&mask]; wp++; op++) + n -= stride; + } + } } } -/* +/* * Returns the log encoded 11-bit values with the horizontal * differencing undone. */ static void horizontalAccumulate11(uint16 *wp, int n, int stride, uint16 *op) { - register unsigned int cr, cg, cb, ca, mask; + register unsigned int cr, cg, cb, ca, mask; if (n >= stride) { - mask = CODE_MASK; - if (stride == 3) { - op[0] = cr = wp[0]; op[1] = cg = wp[1]; op[2] = cb = wp[2]; - n -= 3; - while (n > 0) { - wp += 3; - op += 3; - n -= 3; - op[0] = (cr += wp[0]) & mask; - op[1] = (cg += wp[1]) & mask; - op[2] = (cb += wp[2]) & mask; - } - } else if (stride == 4) { - op[0] = cr = wp[0]; op[1] = cg = wp[1]; - op[2] = cb = wp[2]; op[3] = ca = wp[3]; - n -= 4; - while (n > 0) { - wp += 4; - op += 4; - n -= 4; - op[0] = (cr += wp[0]) & mask; - op[1] = (cg += wp[1]) & mask; - op[2] = (cb += wp[2]) & mask; - op[3] = (ca += wp[3]) & mask; - } - } else { - REPEAT(stride, *op = *wp&mask; wp++; op++) - n -= stride; - while (n > 0) { - REPEAT(stride, - wp[stride] += *wp; *op = *wp&mask; wp++; op++) - n -= stride; - } - } + mask = CODE_MASK; + if (stride == 3) { + op[0] = wp[0]; op[1] = wp[1]; op[2] = wp[2]; + cr = wp[0]; cg = wp[1]; cb = wp[2]; + n -= 3; + while (n > 0) { + wp += 3; + op += 3; + n -= 3; + op[0] = (uint16)((cr += wp[0]) & mask); + op[1] = (uint16)((cg += wp[1]) & mask); + op[2] = (uint16)((cb += wp[2]) & mask); + } + } else if (stride == 4) { + op[0] = wp[0]; op[1] = wp[1]; + op[2] = wp[2]; op[3] = wp[3]; + cr = wp[0]; cg = wp[1]; cb = wp[2]; ca = wp[3]; + n -= 4; + while (n > 0) { + wp += 4; + op += 4; + n -= 4; + op[0] = (uint16)((cr += wp[0]) & mask); + op[1] = (uint16)((cg += wp[1]) & mask); + op[2] = (uint16)((cb += wp[2]) & mask); + op[3] = (uint16)((ca += wp[3]) & mask); + } + } else { + REPEAT(stride, *op = *wp&mask; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = *wp&mask; wp++; op++) + n -= stride; + } + } } } static void horizontalAccumulate8(uint16 *wp, int n, int stride, unsigned char *op, - unsigned char *ToLinear8) + unsigned char *ToLinear8) { register unsigned int cr, cg, cb, ca, mask; if (n >= stride) { - mask = CODE_MASK; - if (stride == 3) { - op[0] = ToLinear8[cr = (wp[0] & mask)]; - op[1] = ToLinear8[cg = (wp[1] & mask)]; - op[2] = ToLinear8[cb = (wp[2] & mask)]; - n -= 3; - while (n > 0) { - n -= 3; - wp += 3; - op += 3; - op[0] = ToLinear8[(cr += wp[0]) & mask]; - op[1] = ToLinear8[(cg += wp[1]) & mask]; - op[2] = ToLinear8[(cb += wp[2]) & mask]; - } - } else if (stride == 4) { - op[0] = ToLinear8[cr = (wp[0] & mask)]; - op[1] = ToLinear8[cg = (wp[1] & mask)]; - op[2] = ToLinear8[cb = (wp[2] & mask)]; - op[3] = ToLinear8[ca = (wp[3] & mask)]; - n -= 4; - while (n > 0) { - n -= 4; - wp += 4; - op += 4; - op[0] = ToLinear8[(cr += wp[0]) & mask]; - op[1] = ToLinear8[(cg += wp[1]) & mask]; - op[2] = ToLinear8[(cb += wp[2]) & mask]; - op[3] = ToLinear8[(ca += wp[3]) & mask]; - } - } else { - REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++) - n -= stride; - while (n > 0) { - REPEAT(stride, - wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++) - n -= stride; - } - } + mask = CODE_MASK; + if (stride == 3) { + op[0] = ToLinear8[cr = (wp[0] & mask)]; + op[1] = ToLinear8[cg = (wp[1] & mask)]; + op[2] = ToLinear8[cb = (wp[2] & mask)]; + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + op += 3; + op[0] = ToLinear8[(cr += wp[0]) & mask]; + op[1] = ToLinear8[(cg += wp[1]) & mask]; + op[2] = ToLinear8[(cb += wp[2]) & mask]; + } + } else if (stride == 4) { + op[0] = ToLinear8[cr = (wp[0] & mask)]; + op[1] = ToLinear8[cg = (wp[1] & mask)]; + op[2] = ToLinear8[cb = (wp[2] & mask)]; + op[3] = ToLinear8[ca = (wp[3] & mask)]; + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + op += 4; + op[0] = ToLinear8[(cr += wp[0]) & mask]; + op[1] = ToLinear8[(cg += wp[1]) & mask]; + op[2] = ToLinear8[(cb += wp[2]) & mask]; + op[3] = ToLinear8[(ca += wp[3]) & mask]; + } + } else { + REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + } + } } } static void horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op, - unsigned char *ToLinear8) + unsigned char *ToLinear8) { register unsigned int cr, cg, cb, ca, mask; register unsigned char t0, t1, t2, t3; if (n >= stride) { - mask = CODE_MASK; - if (stride == 3) { - op[0] = 0; - t1 = ToLinear8[cb = (wp[2] & mask)]; - t2 = ToLinear8[cg = (wp[1] & mask)]; - t3 = ToLinear8[cr = (wp[0] & mask)]; - op[1] = t1; - op[2] = t2; - op[3] = t3; - n -= 3; - while (n > 0) { - n -= 3; - wp += 3; - op += 4; - op[0] = 0; - t1 = ToLinear8[(cb += wp[2]) & mask]; - t2 = ToLinear8[(cg += wp[1]) & mask]; - t3 = ToLinear8[(cr += wp[0]) & mask]; - op[1] = t1; - op[2] = t2; - op[3] = t3; - } - } else if (stride == 4) { - t0 = ToLinear8[ca = (wp[3] & mask)]; - t1 = ToLinear8[cb = (wp[2] & mask)]; - t2 = ToLinear8[cg = (wp[1] & mask)]; - t3 = ToLinear8[cr = (wp[0] & mask)]; - op[0] = t0; - op[1] = t1; - op[2] = t2; - op[3] = t3; - n -= 4; - while (n > 0) { - n -= 4; - wp += 4; - op += 4; - t0 = ToLinear8[(ca += wp[3]) & mask]; - t1 = ToLinear8[(cb += wp[2]) & mask]; - t2 = ToLinear8[(cg += wp[1]) & mask]; - t3 = ToLinear8[(cr += wp[0]) & mask]; - op[0] = t0; - op[1] = t1; - op[2] = t2; - op[3] = t3; - } - } else { - REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++) - n -= stride; - while (n > 0) { - REPEAT(stride, - wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++) - n -= stride; - } - } + mask = CODE_MASK; + if (stride == 3) { + op[0] = 0; + t1 = ToLinear8[cb = (wp[2] & mask)]; + t2 = ToLinear8[cg = (wp[1] & mask)]; + t3 = ToLinear8[cr = (wp[0] & mask)]; + op[1] = t1; + op[2] = t2; + op[3] = t3; + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + op += 4; + op[0] = 0; + t1 = ToLinear8[(cb += wp[2]) & mask]; + t2 = ToLinear8[(cg += wp[1]) & mask]; + t3 = ToLinear8[(cr += wp[0]) & mask]; + op[1] = t1; + op[2] = t2; + op[3] = t3; + } + } else if (stride == 4) { + t0 = ToLinear8[ca = (wp[3] & mask)]; + t1 = ToLinear8[cb = (wp[2] & mask)]; + t2 = ToLinear8[cg = (wp[1] & mask)]; + t3 = ToLinear8[cr = (wp[0] & mask)]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + op += 4; + t0 = ToLinear8[(ca += wp[3]) & mask]; + t1 = ToLinear8[(cb += wp[2]) & mask]; + t2 = ToLinear8[(cg += wp[1]) & mask]; + t3 = ToLinear8[(cr += wp[0]) & mask]; + op[0] = t0; + op[1] = t1; + op[2] = t2; + op[3] = t3; + } + } else { + REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++) + n -= stride; + } + } } } @@ -455,25 +457,26 @@ horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op, * file using PixarLog compression/decompression. */ typedef struct { - TIFFPredictorState predict; - z_stream stream; - uint16 *tbuf; - uint16 stride; - int state; - int user_datafmt; - int quality; + TIFFPredictorState predict; + z_stream stream; + tmsize_t tbuf_size; /* only set/used on reading for now */ + uint16 *tbuf; + uint16 stride; + int state; + int user_datafmt; + int quality; #define PLSTATE_INIT 1 - TIFFVSetMethod vgetparent; /* super-class method */ - TIFFVSetMethod vsetparent; /* super-class method */ - - float *ToLinearF; - uint16 *ToLinear16; - unsigned char *ToLinear8; - uint16 *FromLT2; - uint16 *From14; /* Really for 16-bit data, but we shift down 2 */ - uint16 *From8; + TIFFVSetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + float *ToLinearF; + uint16 *ToLinear16; + unsigned char *ToLinear8; + uint16 *FromLT2; + uint16 *From14; /* Really for 16-bit data, but we shift down 2 */ + uint16 *From8; + } PixarLogState; static int @@ -486,7 +489,7 @@ PixarLogMakeTables(PixarLogState *sp) * 11-bit companded representation. The 11-bit representation has two * distinct regions. A linear bottom end up through .018316 in steps * of about .000073, and a region of constant ratio up to about 25. - * These floating point numbers are stored in the main table ToLinearF. + * These floating point numbers are stored in the main table ToLinearF. * All other tables are derived from this one. The tables (and the * ratios) are continuous at the internal seam. */ @@ -501,7 +504,7 @@ PixarLogMakeTables(PixarLogState *sp) uint16 *From14; /* Really for 16-bit data, but we shift down 2 */ uint16 *From8; - c = log(RATIO); + c = log(RATIO); nlin = (int)(1./c); /* nlin must be an integer */ c = 1./nlin; b = exp(-c*ONE); /* multiplicative scale factor [b*exp(c*ONE) = 1] */ @@ -517,46 +520,46 @@ PixarLogMakeTables(PixarLogState *sp) ToLinear16 = (uint16 *)_TIFFmalloc(TSIZEP1 * sizeof(uint16)); ToLinear8 = (unsigned char *)_TIFFmalloc(TSIZEP1 * sizeof(unsigned char)); if (FromLT2 == NULL || From14 == NULL || From8 == NULL || - ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL) { - if (FromLT2) _TIFFfree(FromLT2); - if (From14) _TIFFfree(From14); - if (From8) _TIFFfree(From8); - if (ToLinearF) _TIFFfree(ToLinearF); - if (ToLinear16) _TIFFfree(ToLinear16); - if (ToLinear8) _TIFFfree(ToLinear8); - sp->FromLT2 = NULL; - sp->From14 = NULL; - sp->From8 = NULL; - sp->ToLinearF = NULL; - sp->ToLinear16 = NULL; - sp->ToLinear8 = NULL; - return 0; + ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL) { + if (FromLT2) _TIFFfree(FromLT2); + if (From14) _TIFFfree(From14); + if (From8) _TIFFfree(From8); + if (ToLinearF) _TIFFfree(ToLinearF); + if (ToLinear16) _TIFFfree(ToLinear16); + if (ToLinear8) _TIFFfree(ToLinear8); + sp->FromLT2 = NULL; + sp->From14 = NULL; + sp->From8 = NULL; + sp->ToLinearF = NULL; + sp->ToLinear16 = NULL; + sp->ToLinear8 = NULL; + return 0; } j = 0; for (i = 0; i < nlin; i++) { - v = i * linstep; - ToLinearF[j++] = (float)v; + v = i * linstep; + ToLinearF[j++] = (float)v; } for (i = nlin; i < TSIZE; i++) - ToLinearF[j++] = (float)(b*exp(c*i)); + ToLinearF[j++] = (float)(b*exp(c*i)); ToLinearF[2048] = ToLinearF[2047]; for (i = 0; i < TSIZEP1; i++) { - v = ToLinearF[i]*65535.0 + 0.5; - ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16)v; - v = ToLinearF[i]*255.0 + 0.5; - ToLinear8[i] = (v > 255.0) ? 255 : (unsigned char)v; + v = ToLinearF[i]*65535.0 + 0.5; + ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16)v; + v = ToLinearF[i]*255.0 + 0.5; + ToLinear8[i] = (v > 255.0) ? 255 : (unsigned char)v; } j = 0; for (i = 0; i < lt2size; i++) { - if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1]) - j++; - FromLT2[i] = j; + if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1]) + j++; + FromLT2[i] = (uint16)j; } /* @@ -566,16 +569,16 @@ PixarLogMakeTables(PixarLogState *sp) */ j = 0; for (i = 0; i < 16384; i++) { - while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1]) - j++; - From14[i] = j; + while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1]) + j++; + From14[i] = (uint16)j; } j = 0; for (i = 0; i < 256; i++) { - while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1]) - j++; - From8[i] = j; + while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1]) + j++; + From8[i] = (uint16)j; } Fltsize = (float)(lt2size/2); @@ -601,97 +604,129 @@ static int PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s); static int PixarLogGuessDataFmt(TIFFDirectory *td) { - int guess = PIXARLOGDATAFMT_UNKNOWN; - int format = td->td_sampleformat; + int guess = PIXARLOGDATAFMT_UNKNOWN; + int format = td->td_sampleformat; - /* If the user didn't tell us his datafmt, - * take our best guess from the bitspersample. - */ - switch (td->td_bitspersample) { - case 32: - if (format == SAMPLEFORMAT_IEEEFP) - guess = PIXARLOGDATAFMT_FLOAT; - break; - case 16: - if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) - guess = PIXARLOGDATAFMT_16BIT; - break; - case 12: - if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT) - guess = PIXARLOGDATAFMT_12BITPICIO; - break; - case 11: - if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) - guess = PIXARLOGDATAFMT_11BITLOG; - break; - case 8: - if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) - guess = PIXARLOGDATAFMT_8BIT; - break; - } + /* If the user didn't tell us his datafmt, + * take our best guess from the bitspersample. + */ + switch (td->td_bitspersample) { + case 32: + if (format == SAMPLEFORMAT_IEEEFP) + guess = PIXARLOGDATAFMT_FLOAT; + break; + case 16: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) + guess = PIXARLOGDATAFMT_16BIT; + break; + case 12: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT) + guess = PIXARLOGDATAFMT_12BITPICIO; + break; + case 11: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) + guess = PIXARLOGDATAFMT_11BITLOG; + break; + case 8: + if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) + guess = PIXARLOGDATAFMT_8BIT; + break; + } - return guess; + return guess; } +#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0)) +#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1) + static tmsize_t multiply_ms(tmsize_t m1, tmsize_t m2) { - tmsize_t bytes = m1 * m2; + if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 ) + return 0; + return m1 * m2; +} - if (m1 && bytes / m1 != m2) - bytes = 0; +static tmsize_t +add_ms(tmsize_t m1, tmsize_t m2) +{ + /* if either input is zero, assume overflow already occurred */ + if (m1 == 0 || m2 == 0) + return 0; + else if (m1 > TIFF_TMSIZE_T_MAX - m2) + return 0; - return bytes; + return m1 + m2; } static int PixarLogFixupTags(TIFF* tif) { - (void) tif; - return (1); + (void) tif; + return (1); } static int PixarLogSetupDecode(TIFF* tif) { - static const char module[] = "PixarLogSetupDecode"; - TIFFDirectory *td = &tif->tif_dir; - PixarLogState* sp = DecoderState(tif); - tmsize_t tbuf_size; + static const char module[] = "PixarLogSetupDecode"; + TIFFDirectory *td = &tif->tif_dir; + PixarLogState* sp = DecoderState(tif); + tmsize_t tbuf_size; + uint32 strip_height; - assert(sp != NULL); + assert(sp != NULL); - /* Make sure no byte swapping happens on the data - * after decompression. */ - tif->tif_postdecode = _TIFFNoPostDecode; + /* This function can possibly be called several times by */ + /* PredictorSetupDecode() if this function succeeds but */ + /* PredictorSetup() fails */ + if( (sp->state & PLSTATE_INIT) != 0 ) + return 1; - /* for some reason, we can't do this in TIFFInitPixarLog */ + strip_height = td->td_rowsperstrip; + if( strip_height > td->td_imagelength ) + strip_height = td->td_imagelength; - sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? - td->td_samplesperpixel : 1); - tbuf_size = multiply_ms(multiply_ms(multiply_ms(sp->stride, td->td_imagewidth), - td->td_rowsperstrip), sizeof(uint16)); - if (tbuf_size == 0) - return (0); /* TODO: this is an error return without error report through TIFFErrorExt */ - sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size+sizeof(uint16)); - if (sp->tbuf == NULL) - return (0); - if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) - sp->user_datafmt = PixarLogGuessDataFmt(td); - if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { - TIFFErrorExt(tif->tif_clientdata, module, - "PixarLog compression can't handle bits depth/data format combination (depth: %d)", - td->td_bitspersample); - return (0); - } + /* Make sure no byte swapping happens on the data + * after decompression. */ + tif->tif_postdecode = _TIFFNoPostDecode; - if (inflateInit(&sp->stream) != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg); - return (0); - } else { - sp->state |= PLSTATE_INIT; - return (1); - } + /* for some reason, we can't do this in TIFFInitPixarLog */ + + sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1); + tbuf_size = multiply_ms(multiply_ms(multiply_ms(sp->stride, td->td_imagewidth), + strip_height), sizeof(uint16)); + /* add one more stride in case input ends mid-stride */ + tbuf_size = add_ms(tbuf_size, sizeof(uint16) * sp->stride); + if (tbuf_size == 0) + return (0); /* TODO: this is an error return without error report through TIFFErrorExt */ + sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size); + if (sp->tbuf == NULL) + return (0); + sp->tbuf_size = tbuf_size; + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) + sp->user_datafmt = PixarLogGuessDataFmt(td); + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { + _TIFFfree(sp->tbuf); + sp->tbuf = NULL; + sp->tbuf_size = 0; + TIFFErrorExt(tif->tif_clientdata, module, + "PixarLog compression can't handle bits depth/data format combination (depth: %d)", + td->td_bitspersample); + return (0); + } + + if (inflateInit(&sp->stream) != Z_OK) { + _TIFFfree(sp->tbuf); + sp->tbuf = NULL; + sp->tbuf_size = 0; + TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg ? sp->stream.msg : "(null)"); + return (0); + } else { + sp->state |= PLSTATE_INIT; + return (1); + } } /* @@ -700,194 +735,207 @@ PixarLogSetupDecode(TIFF* tif) static int PixarLogPreDecode(TIFF* tif, uint16 s) { - static const char module[] = "PixarLogPreDecode"; - PixarLogState* sp = DecoderState(tif); + static const char module[] = "PixarLogPreDecode"; + PixarLogState* sp = DecoderState(tif); - (void) s; - assert(sp != NULL); - sp->stream.next_in = tif->tif_rawdata; - assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, - we need to simplify this code to reflect a ZLib that is likely updated - to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ - sp->stream.avail_in = (uInt) tif->tif_rawcc; - if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) - { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } - return (inflateReset(&sp->stream) == Z_OK); + (void) s; + assert(sp != NULL); + sp->stream.next_in = tif->tif_rawdata; + assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, + we need to simplify this code to reflect a ZLib that is likely updated + to deal with 8byte memory sizes, though this code will respond + appropriately even before we simplify it */ + sp->stream.avail_in = (uInt) tif->tif_rawcc; + if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) + { + TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); + return (0); + } + return (inflateReset(&sp->stream) == Z_OK); } static int PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) { - static const char module[] = "PixarLogDecode"; - TIFFDirectory *td = &tif->tif_dir; - PixarLogState* sp = DecoderState(tif); - tmsize_t i; - tmsize_t nsamples; - int llen; - uint16 *up; + static const char module[] = "PixarLogDecode"; + TIFFDirectory *td = &tif->tif_dir; + PixarLogState* sp = DecoderState(tif); + tmsize_t i; + tmsize_t nsamples; + int llen; + uint16 *up; - switch (sp->user_datafmt) { - case PIXARLOGDATAFMT_FLOAT: - nsamples = occ / sizeof(float); /* XXX float == 32 bits */ - break; - case PIXARLOGDATAFMT_16BIT: - case PIXARLOGDATAFMT_12BITPICIO: - case PIXARLOGDATAFMT_11BITLOG: - nsamples = occ / sizeof(uint16); /* XXX uint16 == 16 bits */ - break; - case PIXARLOGDATAFMT_8BIT: - case PIXARLOGDATAFMT_8BITABGR: - nsamples = occ; - break; - default: - TIFFErrorExt(tif->tif_clientdata, module, - "%d bit input not supported in PixarLog", - td->td_bitspersample); - return 0; - } + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + nsamples = occ / sizeof(float); /* XXX float == 32 bits */ + break; + case PIXARLOGDATAFMT_16BIT: + case PIXARLOGDATAFMT_12BITPICIO: + case PIXARLOGDATAFMT_11BITLOG: + nsamples = occ / sizeof(uint16); /* XXX uint16 == 16 bits */ + break; + case PIXARLOGDATAFMT_8BIT: + case PIXARLOGDATAFMT_8BITABGR: + nsamples = occ; + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, + "%d bit input not supported in PixarLog", + td->td_bitspersample); + return 0; + } - llen = sp->stride * td->td_imagewidth; + llen = sp->stride * td->td_imagewidth; - (void) s; - assert(sp != NULL); - sp->stream.next_out = (unsigned char *) sp->tbuf; - assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, - we need to simplify this code to reflect a ZLib that is likely updated - to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ - sp->stream.avail_out = (uInt) (nsamples * sizeof(uint16)); - if (sp->stream.avail_out != nsamples * sizeof(uint16)) - { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } - do { - int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); - if (state == Z_STREAM_END) { - break; /* XXX */ - } - if (state == Z_DATA_ERROR) { - TIFFErrorExt(tif->tif_clientdata, module, - "Decoding error at scanline %lu, %s", - (unsigned long) tif->tif_row, sp->stream.msg); - if (inflateSync(&sp->stream) != Z_OK) - return (0); - continue; - } - if (state != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", - sp->stream.msg); - return (0); - } - } while (sp->stream.avail_out > 0); + (void) s; + assert(sp != NULL); - /* hopefully, we got all the bytes we needed */ - if (sp->stream.avail_out != 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at scanline %lu (short " TIFF_UINT64_FORMAT " bytes)", - (unsigned long) tif->tif_row, (TIFF_UINT64_T) sp->stream.avail_out); - return (0); - } + sp->stream.next_in = tif->tif_rawcp; + sp->stream.avail_in = (uInt) tif->tif_rawcc; - up = sp->tbuf; - /* Swap bytes in the data if from a different endian machine. */ - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabArrayOfShort(up, nsamples); + sp->stream.next_out = (unsigned char *) sp->tbuf; + assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, + we need to simplify this code to reflect a ZLib that is likely updated + to deal with 8byte memory sizes, though this code will respond + appropriately even before we simplify it */ + sp->stream.avail_out = (uInt) (nsamples * sizeof(uint16)); + if (sp->stream.avail_out != nsamples * sizeof(uint16)) + { + TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); + return (0); + } + /* Check that we will not fill more than what was allocated */ + if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size) + { + TIFFErrorExt(tif->tif_clientdata, module, "sp->stream.avail_out > sp->tbuf_size"); + return (0); + } + do { + int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); + if (state == Z_STREAM_END) { + break; /* XXX */ + } + if (state == Z_DATA_ERROR) { + TIFFErrorExt(tif->tif_clientdata, module, + "Decoding error at scanline %lu, %s", + (unsigned long) tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)"); + if (inflateSync(&sp->stream) != Z_OK) + return (0); + continue; + } + if (state != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", + sp->stream.msg ? sp->stream.msg : "(null)"); + return (0); + } + } while (sp->stream.avail_out > 0); - /* - * if llen is not an exact multiple of nsamples, the decode operation - * may overflow the output buffer, so truncate it enough to prevent - * that but still salvage as much data as possible. - */ - if (nsamples % llen) { - TIFFWarningExt(tif->tif_clientdata, module, - "stride %lu is not a multiple of sample count, " - "%lu, data truncated.", (unsigned long) llen, (unsigned long) nsamples); - nsamples -= nsamples % llen; - } + /* hopefully, we got all the bytes we needed */ + if (sp->stream.avail_out != 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at scanline %lu (short " TIFF_UINT64_FORMAT " bytes)", + (unsigned long) tif->tif_row, (TIFF_UINT64_T) sp->stream.avail_out); + return (0); + } - for (i = 0; i < nsamples; i += llen, up += llen) { - switch (sp->user_datafmt) { - case PIXARLOGDATAFMT_FLOAT: - horizontalAccumulateF(up, llen, sp->stride, - (float *)op, sp->ToLinearF); - op += llen * sizeof(float); - break; - case PIXARLOGDATAFMT_16BIT: - horizontalAccumulate16(up, llen, sp->stride, - (uint16 *)op, sp->ToLinear16); - op += llen * sizeof(uint16); - break; - case PIXARLOGDATAFMT_12BITPICIO: - horizontalAccumulate12(up, llen, sp->stride, - (int16 *)op, sp->ToLinearF); - op += llen * sizeof(int16); - break; - case PIXARLOGDATAFMT_11BITLOG: - horizontalAccumulate11(up, llen, sp->stride, - (uint16 *)op); - op += llen * sizeof(uint16); - break; - case PIXARLOGDATAFMT_8BIT: - horizontalAccumulate8(up, llen, sp->stride, - (unsigned char *)op, sp->ToLinear8); - op += llen * sizeof(unsigned char); - break; - case PIXARLOGDATAFMT_8BITABGR: - horizontalAccumulate8abgr(up, llen, sp->stride, - (unsigned char *)op, sp->ToLinear8); - op += llen * sizeof(unsigned char); - break; - default: - TIFFErrorExt(tif->tif_clientdata, module, - "Unsupported bits/sample: %d", - td->td_bitspersample); - return (0); - } - } + tif->tif_rawcp = sp->stream.next_in; + tif->tif_rawcc = sp->stream.avail_in; - return (1); + up = sp->tbuf; + /* Swap bytes in the data if from a different endian machine. */ + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabArrayOfShort(up, nsamples); + + /* + * if llen is not an exact multiple of nsamples, the decode operation + * may overflow the output buffer, so truncate it enough to prevent + * that but still salvage as much data as possible. + */ + if (nsamples % llen) { + TIFFWarningExt(tif->tif_clientdata, module, + "stride %lu is not a multiple of sample count, " + "%lu, data truncated.", (unsigned long) llen, (unsigned long) nsamples); + nsamples -= nsamples % llen; + } + + for (i = 0; i < nsamples; i += llen, up += llen) { + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + horizontalAccumulateF(up, llen, sp->stride, + (float *)op, sp->ToLinearF); + op += llen * sizeof(float); + break; + case PIXARLOGDATAFMT_16BIT: + horizontalAccumulate16(up, llen, sp->stride, + (uint16 *)op, sp->ToLinear16); + op += llen * sizeof(uint16); + break; + case PIXARLOGDATAFMT_12BITPICIO: + horizontalAccumulate12(up, llen, sp->stride, + (int16 *)op, sp->ToLinearF); + op += llen * sizeof(int16); + break; + case PIXARLOGDATAFMT_11BITLOG: + horizontalAccumulate11(up, llen, sp->stride, + (uint16 *)op); + op += llen * sizeof(uint16); + break; + case PIXARLOGDATAFMT_8BIT: + horizontalAccumulate8(up, llen, sp->stride, + (unsigned char *)op, sp->ToLinear8); + op += llen * sizeof(unsigned char); + break; + case PIXARLOGDATAFMT_8BITABGR: + horizontalAccumulate8abgr(up, llen, sp->stride, + (unsigned char *)op, sp->ToLinear8); + op += llen * sizeof(unsigned char); + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, + "Unsupported bits/sample: %d", + td->td_bitspersample); + return (0); + } + } + + return (1); } static int PixarLogSetupEncode(TIFF* tif) { - static const char module[] = "PixarLogSetupEncode"; - TIFFDirectory *td = &tif->tif_dir; - PixarLogState* sp = EncoderState(tif); - tmsize_t tbuf_size; + static const char module[] = "PixarLogSetupEncode"; + TIFFDirectory *td = &tif->tif_dir; + PixarLogState* sp = EncoderState(tif); + tmsize_t tbuf_size; - assert(sp != NULL); + assert(sp != NULL); - /* for some reason, we can't do this in TIFFInitPixarLog */ + /* for some reason, we can't do this in TIFFInitPixarLog */ - sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? - td->td_samplesperpixel : 1); - tbuf_size = multiply_ms(multiply_ms(multiply_ms(sp->stride, td->td_imagewidth), - td->td_rowsperstrip), sizeof(uint16)); - if (tbuf_size == 0) - return (0); /* TODO: this is an error return without error report through TIFFErrorExt */ - sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size); - if (sp->tbuf == NULL) - return (0); - if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) - sp->user_datafmt = PixarLogGuessDataFmt(td); - if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { - TIFFErrorExt(tif->tif_clientdata, module, "PixarLog compression can't handle %d bit linear encodings", td->td_bitspersample); - return (0); - } + sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1); + tbuf_size = multiply_ms(multiply_ms(multiply_ms(sp->stride, td->td_imagewidth), + td->td_rowsperstrip), sizeof(uint16)); + if (tbuf_size == 0) + return (0); /* TODO: this is an error return without error report through TIFFErrorExt */ + sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size); + if (sp->tbuf == NULL) + return (0); + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) + sp->user_datafmt = PixarLogGuessDataFmt(td); + if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { + TIFFErrorExt(tif->tif_clientdata, module, "PixarLog compression can't handle %d bit linear encodings", td->td_bitspersample); + return (0); + } - if (deflateInit(&sp->stream, sp->quality) != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg); - return (0); - } else { - sp->state |= PLSTATE_INIT; - return (1); - } + if (deflateInit(&sp->stream, sp->quality) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg ? sp->stream.msg : "(null)"); + return (0); + } else { + sp->state |= PLSTATE_INIT; + return (1); + } } /* @@ -896,23 +944,23 @@ PixarLogSetupEncode(TIFF* tif) static int PixarLogPreEncode(TIFF* tif, uint16 s) { - static const char module[] = "PixarLogPreEncode"; - PixarLogState *sp = EncoderState(tif); + static const char module[] = "PixarLogPreEncode"; + PixarLogState *sp = EncoderState(tif); - (void) s; - assert(sp != NULL); - sp->stream.next_out = tif->tif_rawdata; - assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, - we need to simplify this code to reflect a ZLib that is likely updated - to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ - sp->stream.avail_out = tif->tif_rawdatasize; - if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) - { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } - return (deflateReset(&sp->stream) == Z_OK); + (void) s; + assert(sp != NULL); + sp->stream.next_out = tif->tif_rawdata; + assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, + we need to simplify this code to reflect a ZLib that is likely updated + to deal with 8byte memory sizes, though this code will respond + appropriately even before we simplify it */ + sp->stream.avail_out = (uInt)tif->tif_rawdatasize; + if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) + { + TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); + return (0); + } + return (deflateReset(&sp->stream) == Z_OK); } static void @@ -922,59 +970,56 @@ horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2) float fltsize = Fltsize; #define CLAMP(v) ( (v<(float)0.) ? 0 \ - : (v<(float)2.) ? FromLT2[(int)(v*fltsize)] \ - : (v>(float)24.2) ? 2047 \ - : LogK1*log(v*LogK2) + 0.5 ) + : (v<(float)2.) ? FromLT2[(int)(v*fltsize)] \ + : (v>(float)24.2) ? 2047 \ + : LogK1*log(v*LogK2) + 0.5 ) mask = CODE_MASK; if (n >= stride) { - if (stride == 3) { - r2 = wp[0] = (uint16) CLAMP(ip[0]); - g2 = wp[1] = (uint16) CLAMP(ip[1]); - b2 = wp[2] = (uint16) CLAMP(ip[2]); - n -= 3; - while (n > 0) { - n -= 3; - wp += 3; - ip += 3; - r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; - g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; - b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; - } - } else if (stride == 4) { - r2 = wp[0] = (uint16) CLAMP(ip[0]); - g2 = wp[1] = (uint16) CLAMP(ip[1]); - b2 = wp[2] = (uint16) CLAMP(ip[2]); - a2 = wp[3] = (uint16) CLAMP(ip[3]); - n -= 4; - while (n > 0) { - n -= 4; - wp += 4; - ip += 4; - r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; - g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; - b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; - a1 = (int32) CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1; - } - } else { - ip += n - 1; /* point to last one */ - wp += n - 1; /* point to last one */ + if (stride == 3) { + r2 = wp[0] = (uint16) CLAMP(ip[0]); + g2 = wp[1] = (uint16) CLAMP(ip[1]); + b2 = wp[2] = (uint16) CLAMP(ip[2]); + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + ip += 3; + r1 = (int32) CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = (int32) CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = (int32) CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1; + } + } else if (stride == 4) { + r2 = wp[0] = (uint16) CLAMP(ip[0]); + g2 = wp[1] = (uint16) CLAMP(ip[1]); + b2 = wp[2] = (uint16) CLAMP(ip[2]); + a2 = wp[3] = (uint16) CLAMP(ip[3]); + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + ip += 4; + r1 = (int32) CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = (int32) CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = (int32) CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1; + a1 = (int32) CLAMP(ip[3]); wp[3] = (uint16)((a1-a2) & mask); a2 = a1; + } + } else { + REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp++; ip++) n -= stride; while (n > 0) { - REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); - wp[stride] -= wp[0]; - wp[stride] &= mask; - wp--; ip--) - n -= stride; + REPEAT(stride, + wp[0] = (uint16)(((int32)CLAMP(ip[0])-(int32)CLAMP(ip[-stride])) & mask); + wp++; ip++) + n -= stride; } - REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp--; ip--) - } + } } } static void -horizontalDifference16(unsigned short *ip, int n, int stride, - unsigned short *wp, uint16 *From14) +horizontalDifference16(unsigned short *ip, int n, int stride, + unsigned short *wp, uint16 *From14) { register int r1, g1, b1, a1, r2, g2, b2, a2, mask; @@ -984,51 +1029,48 @@ horizontalDifference16(unsigned short *ip, int n, int stride, mask = CODE_MASK; if (n >= stride) { - if (stride == 3) { - r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); - b2 = wp[2] = CLAMP(ip[2]); - n -= 3; - while (n > 0) { - n -= 3; - wp += 3; - ip += 3; - r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; - g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; - b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; + if (stride == 3) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); + n -= 3; + while (n > 0) { + n -= 3; + wp += 3; + ip += 3; + r1 = CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1; + } + } else if (stride == 4) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]); + n -= 4; + while (n > 0) { + n -= 4; + wp += 4; + ip += 4; + r1 = CLAMP(ip[0]); wp[0] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = CLAMP(ip[1]); wp[1] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = CLAMP(ip[2]); wp[2] = (uint16)((b1-b2) & mask); b2 = b1; + a1 = CLAMP(ip[3]); wp[3] = (uint16)((a1-a2) & mask); a2 = a1; + } + } else { + REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++) + n -= stride; + while (n > 0) { + REPEAT(stride, + wp[0] = (uint16)((CLAMP(ip[0])-CLAMP(ip[-stride])) & mask); + wp++; ip++) + n -= stride; } - } else if (stride == 4) { - r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); - b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]); - n -= 4; - while (n > 0) { - n -= 4; - wp += 4; - ip += 4; - r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; - g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; - b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; - a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1; - } - } else { - ip += n - 1; /* point to last one */ - wp += n - 1; /* point to last one */ - n -= stride; - while (n > 0) { - REPEAT(stride, wp[0] = CLAMP(ip[0]); - wp[stride] -= wp[0]; - wp[stride] &= mask; - wp--; ip--) - n -= stride; - } - REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) - } + } } } static void -horizontalDifference8(unsigned char *ip, int n, int stride, - unsigned short *wp, uint16 *From8) +horizontalDifference8(unsigned char *ip, int n, int stride, + unsigned short *wp, uint16 *From8) { register int r1, g1, b1, a1, r2, g2, b2, a2, mask; @@ -1037,43 +1079,40 @@ horizontalDifference8(unsigned char *ip, int n, int stride, mask = CODE_MASK; if (n >= stride) { - if (stride == 3) { - r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); - b2 = wp[2] = CLAMP(ip[2]); - n -= 3; - while (n > 0) { - n -= 3; - r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1; - g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1; - b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1; - wp += 3; - ip += 3; - } - } else if (stride == 4) { - r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); - b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]); - n -= 4; - while (n > 0) { - n -= 4; - r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1; - g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1; - b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1; - a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1; - wp += 4; - ip += 4; - } - } else { - wp += n + stride - 1; /* point to last one */ - ip += n + stride - 1; /* point to last one */ + if (stride == 3) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); + n -= 3; + while (n > 0) { + n -= 3; + r1 = CLAMP(ip[3]); wp[3] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = CLAMP(ip[4]); wp[4] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = CLAMP(ip[5]); wp[5] = (uint16)((b1-b2) & mask); b2 = b1; + wp += 3; + ip += 3; + } + } else if (stride == 4) { + r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); + b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]); + n -= 4; + while (n > 0) { + n -= 4; + r1 = CLAMP(ip[4]); wp[4] = (uint16)((r1-r2) & mask); r2 = r1; + g1 = CLAMP(ip[5]); wp[5] = (uint16)((g1-g2) & mask); g2 = g1; + b1 = CLAMP(ip[6]); wp[6] = (uint16)((b1-b2) & mask); b2 = b1; + a1 = CLAMP(ip[7]); wp[7] = (uint16)((a1-a2) & mask); a2 = a1; + wp += 4; + ip += 4; + } + } else { + REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++) n -= stride; while (n > 0) { - REPEAT(stride, wp[0] = CLAMP(ip[0]); - wp[stride] -= wp[0]; - wp[stride] &= mask; - wp--; ip--) - n -= stride; + REPEAT(stride, + wp[0] = (uint16)((CLAMP(ip[0])-CLAMP(ip[-stride])) & mask); + wp++; ip++) + n -= stride; } - REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) } } } @@ -1084,90 +1123,97 @@ horizontalDifference8(unsigned char *ip, int n, int stride, static int PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - static const char module[] = "PixarLogEncode"; - TIFFDirectory *td = &tif->tif_dir; - PixarLogState *sp = EncoderState(tif); - tmsize_t i; - tmsize_t n; - int llen; - unsigned short * up; + static const char module[] = "PixarLogEncode"; + TIFFDirectory *td = &tif->tif_dir; + PixarLogState *sp = EncoderState(tif); + tmsize_t i; + tmsize_t n; + int llen; + unsigned short * up; - (void) s; + (void) s; - switch (sp->user_datafmt) { - case PIXARLOGDATAFMT_FLOAT: - n = cc / sizeof(float); /* XXX float == 32 bits */ - break; - case PIXARLOGDATAFMT_16BIT: - case PIXARLOGDATAFMT_12BITPICIO: - case PIXARLOGDATAFMT_11BITLOG: - n = cc / sizeof(uint16); /* XXX uint16 == 16 bits */ - break; - case PIXARLOGDATAFMT_8BIT: - case PIXARLOGDATAFMT_8BITABGR: - n = cc; - break; - default: + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + n = cc / sizeof(float); /* XXX float == 32 bits */ + break; + case PIXARLOGDATAFMT_16BIT: + case PIXARLOGDATAFMT_12BITPICIO: + case PIXARLOGDATAFMT_11BITLOG: + n = cc / sizeof(uint16); /* XXX uint16 == 16 bits */ + break; + case PIXARLOGDATAFMT_8BIT: + case PIXARLOGDATAFMT_8BITABGR: + n = cc; + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, + "%d bit input not supported in PixarLog", + td->td_bitspersample); + return 0; + } + + llen = sp->stride * td->td_imagewidth; + /* Check against the number of elements (of size uint16) of sp->tbuf */ + if( n > (tmsize_t)(td->td_rowsperstrip * llen) ) + { TIFFErrorExt(tif->tif_clientdata, module, - "%d bit input not supported in PixarLog", - td->td_bitspersample); + "Too many input bytes provided"); return 0; } - llen = sp->stride * td->td_imagewidth; + for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) { + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_FLOAT: + horizontalDifferenceF((float *)bp, llen, + sp->stride, up, sp->FromLT2); + bp += llen * sizeof(float); + break; + case PIXARLOGDATAFMT_16BIT: + horizontalDifference16((uint16 *)bp, llen, + sp->stride, up, sp->From14); + bp += llen * sizeof(uint16); + break; + case PIXARLOGDATAFMT_8BIT: + horizontalDifference8((unsigned char *)bp, llen, + sp->stride, up, sp->From8); + bp += llen * sizeof(unsigned char); + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, + "%d bit input not supported in PixarLog", + td->td_bitspersample); + return 0; + } + } + + sp->stream.next_in = (unsigned char *) sp->tbuf; + assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, + we need to simplify this code to reflect a ZLib that is likely updated + to deal with 8byte memory sizes, though this code will respond + appropriately even before we simplify it */ + sp->stream.avail_in = (uInt) (n * sizeof(uint16)); + if ((sp->stream.avail_in / sizeof(uint16)) != (uInt) n) + { + TIFFErrorExt(tif->tif_clientdata, module, + "ZLib cannot deal with buffers this size"); + return (0); + } - for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) { - switch (sp->user_datafmt) { - case PIXARLOGDATAFMT_FLOAT: - horizontalDifferenceF((float *)bp, llen, - sp->stride, up, sp->FromLT2); - bp += llen * sizeof(float); - break; - case PIXARLOGDATAFMT_16BIT: - horizontalDifference16((uint16 *)bp, llen, - sp->stride, up, sp->From14); - bp += llen * sizeof(uint16); - break; - case PIXARLOGDATAFMT_8BIT: - horizontalDifference8((unsigned char *)bp, llen, - sp->stride, up, sp->From8); - bp += llen * sizeof(unsigned char); - break; - default: - TIFFErrorExt(tif->tif_clientdata, module, - "%d bit input not supported in PixarLog", - td->td_bitspersample); - return 0; - } - } - - sp->stream.next_in = (unsigned char *) sp->tbuf; - assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, - we need to simplify this code to reflect a ZLib that is likely updated - to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ - sp->stream.avail_in = (uInt) (n * sizeof(uint16)); - if ((sp->stream.avail_in / sizeof(uint16)) != (uInt) n) - { - TIFFErrorExt(tif->tif_clientdata, module, - "ZLib cannot deal with buffers this size"); - return (0); - } - - do { - if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "Encoder error: %s", - sp->stream.msg); - return (0); - } - if (sp->stream.avail_out == 0) { - tif->tif_rawcc = tif->tif_rawdatasize; - TIFFFlushData1(tif); - sp->stream.next_out = tif->tif_rawdata; - sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in PixarLogPreEncode */ - } - } while (sp->stream.avail_in > 0); - return (1); + do { + if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "Encoder error: %s", + sp->stream.msg ? sp->stream.msg : "(null)"); + return (0); + } + if (sp->stream.avail_out == 0) { + tif->tif_rawcc = tif->tif_rawdatasize; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in PixarLogPreEncode */ + } + } while (sp->stream.avail_in > 0); + return (1); } /* @@ -1178,81 +1224,94 @@ PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) static int PixarLogPostEncode(TIFF* tif) { - static const char module[] = "PixarLogPostEncode"; - PixarLogState *sp = EncoderState(tif); - int state; + static const char module[] = "PixarLogPostEncode"; + PixarLogState *sp = EncoderState(tif); + int state; - sp->stream.avail_in = 0; + sp->stream.avail_in = 0; - do { - state = deflate(&sp->stream, Z_FINISH); - switch (state) { - case Z_STREAM_END: - case Z_OK: - if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) { - tif->tif_rawcc = - tif->tif_rawdatasize - sp->stream.avail_out; - TIFFFlushData1(tif); - sp->stream.next_out = tif->tif_rawdata; - sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in PixarLogPreEncode */ - } - break; - default: - TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", - sp->stream.msg); - return (0); - } - } while (state != Z_STREAM_END); - return (1); + do { + state = deflate(&sp->stream, Z_FINISH); + switch (state) { + case Z_STREAM_END: + case Z_OK: + if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) { + tif->tif_rawcc = + tif->tif_rawdatasize - sp->stream.avail_out; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in PixarLogPreEncode */ + } + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", + sp->stream.msg ? sp->stream.msg : "(null)"); + return (0); + } + } while (state != Z_STREAM_END); + return (1); } static void PixarLogClose(TIFF* tif) { - TIFFDirectory *td = &tif->tif_dir; + PixarLogState* sp = (PixarLogState*) tif->tif_data; + TIFFDirectory *td = &tif->tif_dir; - /* In a really sneaky (and really incorrect, and untruthfull, and - * troublesome, and error-prone) maneuver that completely goes against - * the spirit of TIFF, and breaks TIFF, on close, we covertly - * modify both bitspersample and sampleformat in the directory to - * indicate 8-bit linear. This way, the decode "just works" even for - * readers that don't know about PixarLog, or how to set - * the PIXARLOGDATFMT pseudo-tag. - */ - td->td_bitspersample = 8; - td->td_sampleformat = SAMPLEFORMAT_UINT; + assert(sp != 0); + /* In a really sneaky (and really incorrect, and untruthful, and + * troublesome, and error-prone) maneuver that completely goes against + * the spirit of TIFF, and breaks TIFF, on close, we covertly + * modify both bitspersample and sampleformat in the directory to + * indicate 8-bit linear. This way, the decode "just works" even for + * readers that don't know about PixarLog, or how to set + * the PIXARLOGDATFMT pseudo-tag. + */ + + if (sp->state&PLSTATE_INIT) { + /* We test the state to avoid an issue such as in + * http://bugzilla.maptools.org/show_bug.cgi?id=2604 + * What appends in that case is that the bitspersample is 1 and + * a TransferFunction is set. The size of the TransferFunction + * depends on 1<td_bitspersample = 8; + td->td_sampleformat = SAMPLEFORMAT_UINT; + } } static void PixarLogCleanup(TIFF* tif) { - PixarLogState* sp = (PixarLogState*) tif->tif_data; + PixarLogState* sp = (PixarLogState*) tif->tif_data; - assert(sp != 0); + assert(sp != 0); - (void)TIFFPredictorCleanup(tif); + (void)TIFFPredictorCleanup(tif); - tif->tif_tagmethods.vgetfield = sp->vgetparent; - tif->tif_tagmethods.vsetfield = sp->vsetparent; + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; - if (sp->FromLT2) _TIFFfree(sp->FromLT2); - if (sp->From14) _TIFFfree(sp->From14); - if (sp->From8) _TIFFfree(sp->From8); - if (sp->ToLinearF) _TIFFfree(sp->ToLinearF); - if (sp->ToLinear16) _TIFFfree(sp->ToLinear16); - if (sp->ToLinear8) _TIFFfree(sp->ToLinear8); - if (sp->state&PLSTATE_INIT) { - if (tif->tif_mode == O_RDONLY) - inflateEnd(&sp->stream); - else - deflateEnd(&sp->stream); - } - if (sp->tbuf) - _TIFFfree(sp->tbuf); - _TIFFfree(sp); - tif->tif_data = NULL; + if (sp->FromLT2) _TIFFfree(sp->FromLT2); + if (sp->From14) _TIFFfree(sp->From14); + if (sp->From8) _TIFFfree(sp->From8); + if (sp->ToLinearF) _TIFFfree(sp->ToLinearF); + if (sp->ToLinear16) _TIFFfree(sp->ToLinear16); + if (sp->ToLinear8) _TIFFfree(sp->ToLinear8); + if (sp->state&PLSTATE_INIT) { + if (tif->tif_mode == O_RDONLY) + inflateEnd(&sp->stream); + else + deflateEnd(&sp->stream); + } + if (sp->tbuf) + _TIFFfree(sp->tbuf); + _TIFFfree(sp); + tif->tif_data = NULL; - _TIFFSetDefaultCompressionState(tif); + _TIFFSetDefaultCompressionState(tif); } static int @@ -1264,55 +1323,55 @@ PixarLogVSetField(TIFF* tif, uint32 tag, va_list ap) switch (tag) { case TIFFTAG_PIXARLOGQUALITY: - sp->quality = (int) va_arg(ap, int); - if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) { - if (deflateParams(&sp->stream, - sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", - sp->stream.msg); - return (0); - } - } - return (1); + sp->quality = (int) va_arg(ap, int); + if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) { + if (deflateParams(&sp->stream, + sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", + sp->stream.msg ? sp->stream.msg : "(null)"); + return (0); + } + } + return (1); case TIFFTAG_PIXARLOGDATAFMT: - sp->user_datafmt = (int) va_arg(ap, int); - /* Tweak the TIFF header so that the rest of libtiff knows what - * size of data will be passed between app and library, and - * assume that the app knows what it is doing and is not - * confused by these header manipulations... - */ - switch (sp->user_datafmt) { - case PIXARLOGDATAFMT_8BIT: - case PIXARLOGDATAFMT_8BITABGR: - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); - TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); - break; - case PIXARLOGDATAFMT_11BITLOG: - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); - TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); - break; - case PIXARLOGDATAFMT_12BITPICIO: - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); - TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); - break; - case PIXARLOGDATAFMT_16BIT: - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); - TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); - break; - case PIXARLOGDATAFMT_FLOAT: - TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32); - TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); - break; - } - /* - * Must recalculate sizes should bits/sample change. - */ - tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1); - tif->tif_scanlinesize = TIFFScanlineSize(tif); - result = 1; /* NB: pseudo tag */ - break; + sp->user_datafmt = (int) va_arg(ap, int); + /* Tweak the TIFF header so that the rest of libtiff knows what + * size of data will be passed between app and library, and + * assume that the app knows what it is doing and is not + * confused by these header manipulations... + */ + switch (sp->user_datafmt) { + case PIXARLOGDATAFMT_8BIT: + case PIXARLOGDATAFMT_8BITABGR: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + break; + case PIXARLOGDATAFMT_11BITLOG: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + break; + case PIXARLOGDATAFMT_12BITPICIO: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); + break; + case PIXARLOGDATAFMT_16BIT: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + break; + case PIXARLOGDATAFMT_FLOAT: + TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32); + TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); + break; + } + /* + * Must recalculate sizes should bits/sample change. + */ + tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1); + tif->tif_scanlinesize = TIFFScanlineSize(tif); + result = 1; /* NB: pseudo tag */ + break; default: - result = (*sp->vsetparent)(tif, tag, ap); + result = (*sp->vsetparent)(tif, tag, ap); } return (result); } @@ -1324,13 +1383,13 @@ PixarLogVGetField(TIFF* tif, uint32 tag, va_list ap) switch (tag) { case TIFFTAG_PIXARLOGQUALITY: - *va_arg(ap, int*) = sp->quality; - break; + *va_arg(ap, int*) = sp->quality; + break; case TIFFTAG_PIXARLOGDATAFMT: - *va_arg(ap, int*) = sp->user_datafmt; - break; + *va_arg(ap, int*) = sp->user_datafmt; + break; default: - return (*sp->vgetparent)(tif, tag, ap); + return (*sp->vgetparent)(tif, tag, ap); } return (1); } @@ -1343,76 +1402,76 @@ static const TIFFField pixarlogFields[] = { int TIFFInitPixarLog(TIFF* tif, int scheme) { - static const char module[] = "TIFFInitPixarLog"; + static const char module[] = "TIFFInitPixarLog"; - PixarLogState* sp; + PixarLogState* sp; - assert(scheme == COMPRESSION_PIXARLOG); + assert(scheme == COMPRESSION_PIXARLOG); - /* - * Merge codec-specific tag information. - */ - if (!_TIFFMergeFields(tif, pixarlogFields, - TIFFArrayCount(pixarlogFields))) { - TIFFErrorExt(tif->tif_clientdata, module, - "Merging PixarLog codec-specific tags failed"); - return 0; - } + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, pixarlogFields, + TIFFArrayCount(pixarlogFields))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Merging PixarLog codec-specific tags failed"); + return 0; + } - /* - * Allocate state block so tag methods have storage to record values. - */ - tif->tif_data = (uint8*) _TIFFmalloc(sizeof (PixarLogState)); - if (tif->tif_data == NULL) - goto bad; - sp = (PixarLogState*) tif->tif_data; - _TIFFmemset(sp, 0, sizeof (*sp)); - sp->stream.data_type = Z_BINARY; - sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN; + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (uint8*) _TIFFmalloc(sizeof (PixarLogState)); + if (tif->tif_data == NULL) + goto bad; + sp = (PixarLogState*) tif->tif_data; + _TIFFmemset(sp, 0, sizeof (*sp)); + sp->stream.data_type = Z_BINARY; + sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN; - /* - * Install codec methods. - */ - tif->tif_fixuptags = PixarLogFixupTags; - tif->tif_setupdecode = PixarLogSetupDecode; - tif->tif_predecode = PixarLogPreDecode; - tif->tif_decoderow = PixarLogDecode; - tif->tif_decodestrip = PixarLogDecode; - tif->tif_decodetile = PixarLogDecode; - tif->tif_setupencode = PixarLogSetupEncode; - tif->tif_preencode = PixarLogPreEncode; - tif->tif_postencode = PixarLogPostEncode; - tif->tif_encoderow = PixarLogEncode; - tif->tif_encodestrip = PixarLogEncode; - tif->tif_encodetile = PixarLogEncode; - tif->tif_close = PixarLogClose; - tif->tif_cleanup = PixarLogCleanup; + /* + * Install codec methods. + */ + tif->tif_fixuptags = PixarLogFixupTags; + tif->tif_setupdecode = PixarLogSetupDecode; + tif->tif_predecode = PixarLogPreDecode; + tif->tif_decoderow = PixarLogDecode; + tif->tif_decodestrip = PixarLogDecode; + tif->tif_decodetile = PixarLogDecode; + tif->tif_setupencode = PixarLogSetupEncode; + tif->tif_preencode = PixarLogPreEncode; + tif->tif_postencode = PixarLogPostEncode; + tif->tif_encoderow = PixarLogEncode; + tif->tif_encodestrip = PixarLogEncode; + tif->tif_encodetile = PixarLogEncode; + tif->tif_close = PixarLogClose; + tif->tif_cleanup = PixarLogCleanup; - /* Override SetField so we can handle our private pseudo-tag */ - sp->vgetparent = tif->tif_tagmethods.vgetfield; - tif->tif_tagmethods.vgetfield = PixarLogVGetField; /* hook for codec tags */ - sp->vsetparent = tif->tif_tagmethods.vsetfield; - tif->tif_tagmethods.vsetfield = PixarLogVSetField; /* hook for codec tags */ + /* Override SetField so we can handle our private pseudo-tag */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = PixarLogVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = PixarLogVSetField; /* hook for codec tags */ - /* Default values for codec-specific fields */ - sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */ - sp->state = 0; + /* Default values for codec-specific fields */ + sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */ + sp->state = 0; - /* we don't wish to use the predictor, - * the default is none, which predictor value 1 - */ - (void) TIFFPredictorInit(tif); + /* we don't wish to use the predictor, + * the default is none, which predictor value 1 + */ + (void) TIFFPredictorInit(tif); - /* - * build the companding tables - */ - PixarLogMakeTables(sp); + /* + * build the companding tables + */ + PixarLogMakeTables(sp); - return (1); + return (1); bad: - TIFFErrorExt(tif->tif_clientdata, module, - "No space for PixarLog state block"); - return (0); + TIFFErrorExt(tif->tif_clientdata, module, + "No space for PixarLog state block"); + return (0); } #endif /* PIXARLOG_SUPPORT */ diff --git a/3rdparty/libtiff/tif_predict.c b/3rdparty/libtiff/tif_predict.c index 2fb18371ed..9ae1f57a65 100644 --- a/3rdparty/libtiff/tif_predict.c +++ b/3rdparty/libtiff/tif_predict.c @@ -1,26 +1,26 @@ -/* $Id: tif_predict.c,v 1.32 2010-03-10 18:56:49 bfriesen Exp $ */ +/* $Id: tif_predict.c,v 1.44 2017-06-18 10:31:50 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -34,16 +34,18 @@ #define PredictorState(tif) ((TIFFPredictorState*) (tif)->tif_data) -static void horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc); -static void horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc); -static void horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc); -static void swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc); -static void swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc); -static void horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc); -static void horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc); -static void horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc); -static void fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc); -static void fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc); +static int swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc); +static int swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc); +static int horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc); +static int swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc); +static int swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc); +static int fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc); +static int fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc); static int PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s); static int PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s); static int PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s); @@ -52,73 +54,85 @@ static int PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s); static int PredictorSetup(TIFF* tif) { - static const char module[] = "PredictorSetup"; + static const char module[] = "PredictorSetup"; - TIFFPredictorState* sp = PredictorState(tif); - TIFFDirectory* td = &tif->tif_dir; + TIFFPredictorState* sp = PredictorState(tif); + TIFFDirectory* td = &tif->tif_dir; - switch (sp->predictor) /* no differencing */ - { - case PREDICTOR_NONE: - return 1; - case PREDICTOR_HORIZONTAL: - if (td->td_bitspersample != 8 - && td->td_bitspersample != 16 - && td->td_bitspersample != 32) { - TIFFErrorExt(tif->tif_clientdata, module, - "Horizontal differencing \"Predictor\" not supported with %d-bit samples", - td->td_bitspersample); - return 0; - } - break; - case PREDICTOR_FLOATINGPOINT: - if (td->td_sampleformat != SAMPLEFORMAT_IEEEFP) { - TIFFErrorExt(tif->tif_clientdata, module, - "Floating point \"Predictor\" not supported with %d data format", - td->td_sampleformat); - return 0; - } - break; - default: - TIFFErrorExt(tif->tif_clientdata, module, - "\"Predictor\" value %d not supported", - sp->predictor); - return 0; - } - sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? - td->td_samplesperpixel : 1); - /* - * Calculate the scanline/tile-width size in bytes. - */ - if (isTiled(tif)) - sp->rowsize = TIFFTileRowSize(tif); - else - sp->rowsize = TIFFScanlineSize(tif); - if (sp->rowsize == 0) - return 0; + switch (sp->predictor) /* no differencing */ + { + case PREDICTOR_NONE: + return 1; + case PREDICTOR_HORIZONTAL: + if (td->td_bitspersample != 8 + && td->td_bitspersample != 16 + && td->td_bitspersample != 32) { + TIFFErrorExt(tif->tif_clientdata, module, + "Horizontal differencing \"Predictor\" not supported with %d-bit samples", + td->td_bitspersample); + return 0; + } + break; + case PREDICTOR_FLOATINGPOINT: + if (td->td_sampleformat != SAMPLEFORMAT_IEEEFP) { + TIFFErrorExt(tif->tif_clientdata, module, + "Floating point \"Predictor\" not supported with %d data format", + td->td_sampleformat); + return 0; + } + if (td->td_bitspersample != 16 + && td->td_bitspersample != 24 + && td->td_bitspersample != 32 + && td->td_bitspersample != 64) { /* Should 64 be allowed? */ + TIFFErrorExt(tif->tif_clientdata, module, + "Floating point \"Predictor\" not supported with %d-bit samples", + td->td_bitspersample); + return 0; + } + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, + "\"Predictor\" value %d not supported", + sp->predictor); + return 0; + } + sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? + td->td_samplesperpixel : 1); + /* + * Calculate the scanline/tile-width size in bytes. + */ + if (isTiled(tif)) + sp->rowsize = TIFFTileRowSize(tif); + else + sp->rowsize = TIFFScanlineSize(tif); + if (sp->rowsize == 0) + return 0; - return 1; + return 1; } static int PredictorSetupDecode(TIFF* tif) { - TIFFPredictorState* sp = PredictorState(tif); - TIFFDirectory* td = &tif->tif_dir; + TIFFPredictorState* sp = PredictorState(tif); + TIFFDirectory* td = &tif->tif_dir; - if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif)) - return 0; + /* Note: when PredictorSetup() fails, the effets of setupdecode() */ + /* will not be "cancelled" so setupdecode() might be robust to */ + /* be called several times. */ + if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif)) + return 0; - if (sp->predictor == 2) { - switch (td->td_bitspersample) { - case 8: sp->decodepfunc = horAcc8; break; - case 16: sp->decodepfunc = horAcc16; break; - case 32: sp->decodepfunc = horAcc32; break; - } - /* - * Override default decoding method with one that does the - * predictor stuff. - */ + if (sp->predictor == 2) { + switch (td->td_bitspersample) { + case 8: sp->decodepfunc = horAcc8; break; + case 16: sp->decodepfunc = horAcc16; break; + case 32: sp->decodepfunc = horAcc32; break; + } + /* + * Override default decoding method with one that does the + * predictor stuff. + */ if( tif->tif_decoderow != PredictorDecodeRow ) { sp->decoderow = tif->tif_decoderow; @@ -129,30 +143,30 @@ PredictorSetupDecode(TIFF* tif) tif->tif_decodetile = PredictorDecodeTile; } - /* - * If the data is horizontally differenced 16-bit data that - * requires byte-swapping, then it must be byte swapped before - * the accumulation step. We do this with a special-purpose - * routine and override the normal post decoding logic that - * the library setup when the directory was read. - */ - if (tif->tif_flags & TIFF_SWAB) { - if (sp->decodepfunc == horAcc16) { - sp->decodepfunc = swabHorAcc16; - tif->tif_postdecode = _TIFFNoPostDecode; + /* + * If the data is horizontally differenced 16-bit data that + * requires byte-swapping, then it must be byte swapped before + * the accumulation step. We do this with a special-purpose + * routine and override the normal post decoding logic that + * the library setup when the directory was read. + */ + if (tif->tif_flags & TIFF_SWAB) { + if (sp->decodepfunc == horAcc16) { + sp->decodepfunc = swabHorAcc16; + tif->tif_postdecode = _TIFFNoPostDecode; } else if (sp->decodepfunc == horAcc32) { - sp->decodepfunc = swabHorAcc32; - tif->tif_postdecode = _TIFFNoPostDecode; + sp->decodepfunc = swabHorAcc32; + tif->tif_postdecode = _TIFFNoPostDecode; } - } - } + } + } - else if (sp->predictor == 3) { - sp->decodepfunc = fpAcc; - /* - * Override default decoding method with one that does the - * predictor stuff. - */ + else if (sp->predictor == 3) { + sp->decodepfunc = fpAcc; + /* + * Override default decoding method with one that does the + * predictor stuff. + */ if( tif->tif_decoderow != PredictorDecodeRow ) { sp->decoderow = tif->tif_decoderow; @@ -162,42 +176,76 @@ PredictorSetupDecode(TIFF* tif) sp->decodetile = tif->tif_decodetile; tif->tif_decodetile = PredictorDecodeTile; } - /* - * The data should not be swapped outside of the floating - * point predictor, the accumulation routine should return - * byres in the native order. - */ - if (tif->tif_flags & TIFF_SWAB) { - tif->tif_postdecode = _TIFFNoPostDecode; - } - /* - * Allocate buffer to keep the decoded bytes before - * rearranging in the ight order - */ - } + /* + * The data should not be swapped outside of the floating + * point predictor, the accumulation routine should return + * byres in the native order. + */ + if (tif->tif_flags & TIFF_SWAB) { + tif->tif_postdecode = _TIFFNoPostDecode; + } + /* + * Allocate buffer to keep the decoded bytes before + * rearranging in the right order + */ + } - return 1; + return 1; } static int PredictorSetupEncode(TIFF* tif) { - TIFFPredictorState* sp = PredictorState(tif); - TIFFDirectory* td = &tif->tif_dir; + TIFFPredictorState* sp = PredictorState(tif); + TIFFDirectory* td = &tif->tif_dir; - if (!(*sp->setupencode)(tif) || !PredictorSetup(tif)) - return 0; + if (!(*sp->setupencode)(tif) || !PredictorSetup(tif)) + return 0; - if (sp->predictor == 2) { - switch (td->td_bitspersample) { - case 8: sp->encodepfunc = horDiff8; break; - case 16: sp->encodepfunc = horDiff16; break; - case 32: sp->encodepfunc = horDiff32; break; + if (sp->predictor == 2) { + switch (td->td_bitspersample) { + case 8: sp->encodepfunc = horDiff8; break; + case 16: sp->encodepfunc = horDiff16; break; + case 32: sp->encodepfunc = horDiff32; break; + } + /* + * Override default encoding method with one that does the + * predictor stuff. + */ + if( tif->tif_encoderow != PredictorEncodeRow ) + { + sp->encoderow = tif->tif_encoderow; + tif->tif_encoderow = PredictorEncodeRow; + sp->encodestrip = tif->tif_encodestrip; + tif->tif_encodestrip = PredictorEncodeTile; + sp->encodetile = tif->tif_encodetile; + tif->tif_encodetile = PredictorEncodeTile; + } + + /* + * If the data is horizontally differenced 16-bit data that + * requires byte-swapping, then it must be byte swapped after + * the differentiation step. We do this with a special-purpose + * routine and override the normal post decoding logic that + * the library setup when the directory was read. + */ + if (tif->tif_flags & TIFF_SWAB) { + if (sp->encodepfunc == horDiff16) { + sp->encodepfunc = swabHorDiff16; + tif->tif_postdecode = _TIFFNoPostDecode; + } else if (sp->encodepfunc == horDiff32) { + sp->encodepfunc = swabHorDiff32; + tif->tif_postdecode = _TIFFNoPostDecode; + } + } } - /* - * Override default encoding method with one that does the - * predictor stuff. - */ + + else if (sp->predictor == 3) { + sp->encodepfunc = fpDiff; + /* + * Override default encoding method with one that does the + * predictor stuff. + */ if( tif->tif_encoderow != PredictorEncodeRow ) { sp->encoderow = tif->tif_encoderow; @@ -207,199 +255,201 @@ PredictorSetupEncode(TIFF* tif) sp->encodetile = tif->tif_encodetile; tif->tif_encodetile = PredictorEncodeTile; } - } + } - else if (sp->predictor == 3) { - sp->encodepfunc = fpDiff; - /* - * Override default encoding method with one that does the - * predictor stuff. - */ - if( tif->tif_encoderow != PredictorEncodeRow ) - { - sp->encoderow = tif->tif_encoderow; - tif->tif_encoderow = PredictorEncodeRow; - sp->encodestrip = tif->tif_encodestrip; - tif->tif_encodestrip = PredictorEncodeTile; - sp->encodetile = tif->tif_encodetile; - tif->tif_encodetile = PredictorEncodeTile; - } - } - - return 1; + return 1; } #define REPEAT4(n, op) \ switch (n) { \ - default: { tmsize_t i; for (i = n-4; i > 0; i--) { op; } } \ - case 4: op; \ - case 3: op; \ - case 2: op; \ - case 1: op; \ + default: { \ + tmsize_t i; for (i = n-4; i > 0; i--) { op; } } /*-fallthrough*/ \ + case 4: op; /*-fallthrough*/ \ + case 3: op; /*-fallthrough*/ \ + case 2: op; /*-fallthrough*/ \ + case 1: op; /*-fallthrough*/ \ case 0: ; \ } -static void +/* Remarks related to C standard compliance in all below functions : */ +/* - to avoid any undefined behaviour, we only operate on unsigned types */ +/* since the behaviour of "overflows" is defined (wrap over) */ +/* - when storing into the byte stream, we explicitly mask with 0xff so */ +/* as to make icc -check=conversions happy (not necessary by the standard) */ + +TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW +static int horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc) { - tmsize_t stride = PredictorState(tif)->stride; + tmsize_t stride = PredictorState(tif)->stride; - char* cp = (char*) cp0; - assert((cc%stride)==0); - if (cc > stride) { - /* - * Pipeline the most common cases. - */ - if (stride == 3) { - unsigned int cr = cp[0]; - unsigned int cg = cp[1]; - unsigned int cb = cp[2]; - cc -= 3; - cp += 3; - while (cc>0) { - cp[0] = (char) (cr += cp[0]); - cp[1] = (char) (cg += cp[1]); - cp[2] = (char) (cb += cp[2]); - cc -= 3; - cp += 3; - } - } else if (stride == 4) { - unsigned int cr = cp[0]; - unsigned int cg = cp[1]; - unsigned int cb = cp[2]; - unsigned int ca = cp[3]; - cc -= 4; - cp += 4; - while (cc>0) { - cp[0] = (char) (cr += cp[0]); - cp[1] = (char) (cg += cp[1]); - cp[2] = (char) (cb += cp[2]); - cp[3] = (char) (ca += cp[3]); - cc -= 4; - cp += 4; - } - } else { - cc -= stride; - do { - REPEAT4(stride, cp[stride] = - (char) (cp[stride] + *cp); cp++) - cc -= stride; - } while (cc>0); - } + unsigned char* cp = (unsigned char*) cp0; + if((cc%stride)!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horAcc8", + "%s", "(cc%stride)!=0"); + return 0; } + + if (cc > stride) { + /* + * Pipeline the most common cases. + */ + if (stride == 3) { + unsigned int cr = cp[0]; + unsigned int cg = cp[1]; + unsigned int cb = cp[2]; + cc -= 3; + cp += 3; + while (cc>0) { + cp[0] = (unsigned char) ((cr += cp[0]) & 0xff); + cp[1] = (unsigned char) ((cg += cp[1]) & 0xff); + cp[2] = (unsigned char) ((cb += cp[2]) & 0xff); + cc -= 3; + cp += 3; + } + } else if (stride == 4) { + unsigned int cr = cp[0]; + unsigned int cg = cp[1]; + unsigned int cb = cp[2]; + unsigned int ca = cp[3]; + cc -= 4; + cp += 4; + while (cc>0) { + cp[0] = (unsigned char) ((cr += cp[0]) & 0xff); + cp[1] = (unsigned char) ((cg += cp[1]) & 0xff); + cp[2] = (unsigned char) ((cb += cp[2]) & 0xff); + cp[3] = (unsigned char) ((ca += cp[3]) & 0xff); + cc -= 4; + cp += 4; + } + } else { + cc -= stride; + do { + REPEAT4(stride, cp[stride] = + (unsigned char) ((cp[stride] + *cp) & 0xff); cp++) + cc -= stride; + } while (cc>0); + } + } + return 1; } -static void +static int swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc) { - tmsize_t stride = PredictorState(tif)->stride; - uint16* wp = (uint16*) cp0; - tmsize_t wc = cc / 2; + uint16* wp = (uint16*) cp0; + tmsize_t wc = cc / 2; - assert((cc%(2*stride))==0); - - if (wc > stride) { TIFFSwabArrayOfShort(wp, wc); - wc -= stride; - do { - REPEAT4(stride, wp[stride] += wp[0]; wp++) - wc -= stride; - } while (wc > 0); - } + return horAcc16(tif, cp0, cc); } -static void +TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW +static int horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc) { - tmsize_t stride = PredictorState(tif)->stride; - uint16* wp = (uint16*) cp0; - tmsize_t wc = cc / 2; + tmsize_t stride = PredictorState(tif)->stride; + uint16* wp = (uint16*) cp0; + tmsize_t wc = cc / 2; - assert((cc%(2*stride))==0); - - if (wc > stride) { - wc -= stride; - do { - REPEAT4(stride, wp[stride] += wp[0]; wp++) - wc -= stride; - } while (wc > 0); + if((cc%(2*stride))!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horAcc16", + "%s", "cc%(2*stride))!=0"); + return 0; } + + if (wc > stride) { + wc -= stride; + do { + REPEAT4(stride, wp[stride] = (uint16)(((unsigned int)wp[stride] + (unsigned int)wp[0]) & 0xffff); wp++) + wc -= stride; + } while (wc > 0); + } + return 1; } -static void +static int swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc) { - tmsize_t stride = PredictorState(tif)->stride; - uint32* wp = (uint32*) cp0; - tmsize_t wc = cc / 4; + uint32* wp = (uint32*) cp0; + tmsize_t wc = cc / 4; - assert((cc%(4*stride))==0); - - if (wc > stride) { TIFFSwabArrayOfLong(wp, wc); - wc -= stride; - do { - REPEAT4(stride, wp[stride] += wp[0]; wp++) - wc -= stride; - } while (wc > 0); - } + return horAcc32(tif, cp0, cc); } -static void +TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW +static int horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc) { - tmsize_t stride = PredictorState(tif)->stride; - uint32* wp = (uint32*) cp0; - tmsize_t wc = cc / 4; + tmsize_t stride = PredictorState(tif)->stride; + uint32* wp = (uint32*) cp0; + tmsize_t wc = cc / 4; - assert((cc%(4*stride))==0); - - if (wc > stride) { - wc -= stride; - do { - REPEAT4(stride, wp[stride] += wp[0]; wp++) - wc -= stride; - } while (wc > 0); + if((cc%(4*stride))!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horAcc32", + "%s", "cc%(4*stride))!=0"); + return 0; } + + if (wc > stride) { + wc -= stride; + do { + REPEAT4(stride, wp[stride] += wp[0]; wp++) + wc -= stride; + } while (wc > 0); + } + return 1; } /* * Floating point predictor accumulation routine. */ -static void +static int fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc) { - tmsize_t stride = PredictorState(tif)->stride; - uint32 bps = tif->tif_dir.td_bitspersample / 8; - tmsize_t wc = cc / bps; - tmsize_t count = cc; - uint8 *cp = (uint8 *) cp0; - uint8 *tmp = (uint8 *)_TIFFmalloc(cc); + tmsize_t stride = PredictorState(tif)->stride; + uint32 bps = tif->tif_dir.td_bitspersample / 8; + tmsize_t wc = cc / bps; + tmsize_t count = cc; + uint8 *cp = (uint8 *) cp0; + uint8 *tmp; - assert((cc%(bps*stride))==0); - - if (!tmp) - return; - - while (count > stride) { - REPEAT4(stride, cp[stride] += cp[0]; cp++) - count -= stride; + if(cc%(bps*stride)!=0) + { + TIFFErrorExt(tif->tif_clientdata, "fpAcc", + "%s", "cc%(bps*stride))!=0"); + return 0; } - _TIFFmemcpy(tmp, cp0, cc); - cp = (uint8 *) cp0; - for (count = 0; count < wc; count++) { - uint32 byte; - for (byte = 0; byte < bps; byte++) { - #if WORDS_BIGENDIAN - cp[bps * count + byte] = tmp[byte * wc + count]; - #else - cp[bps * count + byte] = - tmp[(bps - byte - 1) * wc + count]; - #endif - } - } - _TIFFfree(tmp); + tmp = (uint8 *)_TIFFmalloc(cc); + if (!tmp) + return 0; + + while (count > stride) { + REPEAT4(stride, cp[stride] = + (unsigned char) ((cp[stride] + cp[0]) & 0xff); cp++) + count -= stride; + } + + _TIFFmemcpy(tmp, cp0, cc); + cp = (uint8 *) cp0; + for (count = 0; count < wc; count++) { + uint32 byte; + for (byte = 0; byte < bps; byte++) { + #if WORDS_BIGENDIAN + cp[bps * count + byte] = tmp[byte * wc + count]; + #else + cp[bps * count + byte] = + tmp[(bps - byte - 1) * wc + count]; + #endif + } + } + _TIFFfree(tmp); + return 1; } /* @@ -408,17 +458,16 @@ fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc) static int PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) { - TIFFPredictorState *sp = PredictorState(tif); + TIFFPredictorState *sp = PredictorState(tif); - assert(sp != NULL); - assert(sp->decoderow != NULL); - assert(sp->decodepfunc != NULL); + assert(sp != NULL); + assert(sp->decoderow != NULL); + assert(sp->decodepfunc != NULL); - if ((*sp->decoderow)(tif, op0, occ0, s)) { - (*sp->decodepfunc)(tif, op0, occ0); - return 1; - } else - return 0; + if ((*sp->decoderow)(tif, op0, occ0, s)) { + return (*sp->decodepfunc)(tif, op0, occ0); + } else + return 0; } /* @@ -431,187 +480,249 @@ PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) static int PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) { - TIFFPredictorState *sp = PredictorState(tif); + TIFFPredictorState *sp = PredictorState(tif); - assert(sp != NULL); - assert(sp->decodetile != NULL); + assert(sp != NULL); + assert(sp->decodetile != NULL); - if ((*sp->decodetile)(tif, op0, occ0, s)) { - tmsize_t rowsize = sp->rowsize; - assert(rowsize > 0); - assert((occ0%rowsize)==0); - assert(sp->decodepfunc != NULL); - while (occ0 > 0) { - (*sp->decodepfunc)(tif, op0, rowsize); - occ0 -= rowsize; - op0 += rowsize; + if ((*sp->decodetile)(tif, op0, occ0, s)) { + tmsize_t rowsize = sp->rowsize; + assert(rowsize > 0); + if((occ0%rowsize) !=0) + { + TIFFErrorExt(tif->tif_clientdata, "PredictorDecodeTile", + "%s", "occ0%rowsize != 0"); + return 0; } - return 1; - } else - return 0; + assert(sp->decodepfunc != NULL); + while (occ0 > 0) { + if( !(*sp->decodepfunc)(tif, op0, rowsize) ) + return 0; + occ0 -= rowsize; + op0 += rowsize; + } + return 1; + } else + return 0; } -static void +TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW +static int horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc) { - TIFFPredictorState* sp = PredictorState(tif); - tmsize_t stride = sp->stride; - char* cp = (char*) cp0; + TIFFPredictorState* sp = PredictorState(tif); + tmsize_t stride = sp->stride; + unsigned char* cp = (unsigned char*) cp0; - assert((cc%stride)==0); - - if (cc > stride) { - cc -= stride; - /* - * Pipeline the most common cases. - */ - if (stride == 3) { - int r1, g1, b1; - int r2 = cp[0]; - int g2 = cp[1]; - int b2 = cp[2]; - do { - r1 = cp[3]; cp[3] = r1-r2; r2 = r1; - g1 = cp[4]; cp[4] = g1-g2; g2 = g1; - b1 = cp[5]; cp[5] = b1-b2; b2 = b1; - cp += 3; - } while ((cc -= 3) > 0); - } else if (stride == 4) { - int r1, g1, b1, a1; - int r2 = cp[0]; - int g2 = cp[1]; - int b2 = cp[2]; - int a2 = cp[3]; - do { - r1 = cp[4]; cp[4] = r1-r2; r2 = r1; - g1 = cp[5]; cp[5] = g1-g2; g2 = g1; - b1 = cp[6]; cp[6] = b1-b2; b2 = b1; - a1 = cp[7]; cp[7] = a1-a2; a2 = a1; - cp += 4; - } while ((cc -= 4) > 0); - } else { - cp += cc - 1; - do { - REPEAT4(stride, cp[stride] -= cp[0]; cp--) - } while ((cc -= stride) > 0); - } + if((cc%stride)!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horDiff8", + "%s", "(cc%stride)!=0"); + return 0; } + + if (cc > stride) { + cc -= stride; + /* + * Pipeline the most common cases. + */ + if (stride == 3) { + unsigned int r1, g1, b1; + unsigned int r2 = cp[0]; + unsigned int g2 = cp[1]; + unsigned int b2 = cp[2]; + do { + r1 = cp[3]; cp[3] = (unsigned char)((r1-r2)&0xff); r2 = r1; + g1 = cp[4]; cp[4] = (unsigned char)((g1-g2)&0xff); g2 = g1; + b1 = cp[5]; cp[5] = (unsigned char)((b1-b2)&0xff); b2 = b1; + cp += 3; + } while ((cc -= 3) > 0); + } else if (stride == 4) { + unsigned int r1, g1, b1, a1; + unsigned int r2 = cp[0]; + unsigned int g2 = cp[1]; + unsigned int b2 = cp[2]; + unsigned int a2 = cp[3]; + do { + r1 = cp[4]; cp[4] = (unsigned char)((r1-r2)&0xff); r2 = r1; + g1 = cp[5]; cp[5] = (unsigned char)((g1-g2)&0xff); g2 = g1; + b1 = cp[6]; cp[6] = (unsigned char)((b1-b2)&0xff); b2 = b1; + a1 = cp[7]; cp[7] = (unsigned char)((a1-a2)&0xff); a2 = a1; + cp += 4; + } while ((cc -= 4) > 0); + } else { + cp += cc - 1; + do { + REPEAT4(stride, cp[stride] = (unsigned char)((cp[stride] - cp[0])&0xff); cp--) + } while ((cc -= stride) > 0); + } + } + return 1; } -static void +TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW +static int horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc) { - TIFFPredictorState* sp = PredictorState(tif); - tmsize_t stride = sp->stride; - int16 *wp = (int16*) cp0; - tmsize_t wc = cc/2; + TIFFPredictorState* sp = PredictorState(tif); + tmsize_t stride = sp->stride; + uint16 *wp = (uint16*) cp0; + tmsize_t wc = cc/2; - assert((cc%(2*stride))==0); - - if (wc > stride) { - wc -= stride; - wp += wc - 1; - do { - REPEAT4(stride, wp[stride] -= wp[0]; wp--) - wc -= stride; - } while (wc > 0); + if((cc%(2*stride))!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horDiff8", + "%s", "(cc%(2*stride))!=0"); + return 0; } + + if (wc > stride) { + wc -= stride; + wp += wc - 1; + do { + REPEAT4(stride, wp[stride] = (uint16)(((unsigned int)wp[stride] - (unsigned int)wp[0]) & 0xffff); wp--) + wc -= stride; + } while (wc > 0); + } + return 1; } -static void +static int +swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc) +{ + uint16* wp = (uint16*) cp0; + tmsize_t wc = cc / 2; + + if( !horDiff16(tif, cp0, cc) ) + return 0; + + TIFFSwabArrayOfShort(wp, wc); + return 1; +} + +TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW +static int horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc) { - TIFFPredictorState* sp = PredictorState(tif); - tmsize_t stride = sp->stride; - int32 *wp = (int32*) cp0; - tmsize_t wc = cc/4; + TIFFPredictorState* sp = PredictorState(tif); + tmsize_t stride = sp->stride; + uint32 *wp = (uint32*) cp0; + tmsize_t wc = cc/4; - assert((cc%(4*stride))==0); - - if (wc > stride) { - wc -= stride; - wp += wc - 1; - do { - REPEAT4(stride, wp[stride] -= wp[0]; wp--) - wc -= stride; - } while (wc > 0); + if((cc%(4*stride))!=0) + { + TIFFErrorExt(tif->tif_clientdata, "horDiff32", + "%s", "(cc%(4*stride))!=0"); + return 0; } + + if (wc > stride) { + wc -= stride; + wp += wc - 1; + do { + REPEAT4(stride, wp[stride] -= wp[0]; wp--) + wc -= stride; + } while (wc > 0); + } + return 1; +} + +static int +swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc) +{ + uint32* wp = (uint32*) cp0; + tmsize_t wc = cc / 4; + + if( !horDiff32(tif, cp0, cc) ) + return 0; + + TIFFSwabArrayOfLong(wp, wc); + return 1; } /* * Floating point predictor differencing routine. */ -static void +TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW +static int fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc) { - tmsize_t stride = PredictorState(tif)->stride; - uint32 bps = tif->tif_dir.td_bitspersample / 8; - tmsize_t wc = cc / bps; - tmsize_t count; - uint8 *cp = (uint8 *) cp0; - uint8 *tmp = (uint8 *)_TIFFmalloc(cc); + tmsize_t stride = PredictorState(tif)->stride; + uint32 bps = tif->tif_dir.td_bitspersample / 8; + tmsize_t wc = cc / bps; + tmsize_t count; + uint8 *cp = (uint8 *) cp0; + uint8 *tmp; - assert((cc%(bps*stride))==0); - - if (!tmp) - return; - - _TIFFmemcpy(tmp, cp0, cc); - for (count = 0; count < wc; count++) { - uint32 byte; - for (byte = 0; byte < bps; byte++) { - #if WORDS_BIGENDIAN - cp[byte * wc + count] = tmp[bps * count + byte]; - #else - cp[(bps - byte - 1) * wc + count] = - tmp[bps * count + byte]; - #endif - } + if((cc%(bps*stride))!=0) + { + TIFFErrorExt(tif->tif_clientdata, "fpDiff", + "%s", "(cc%(bps*stride))!=0"); + return 0; } - _TIFFfree(tmp); - cp = (uint8 *) cp0; - cp += cc - stride - 1; - for (count = cc; count > stride; count -= stride) - REPEAT4(stride, cp[stride] -= cp[0]; cp--) + tmp = (uint8 *)_TIFFmalloc(cc); + if (!tmp) + return 0; + + _TIFFmemcpy(tmp, cp0, cc); + for (count = 0; count < wc; count++) { + uint32 byte; + for (byte = 0; byte < bps; byte++) { + #if WORDS_BIGENDIAN + cp[byte * wc + count] = tmp[bps * count + byte]; + #else + cp[(bps - byte - 1) * wc + count] = + tmp[bps * count + byte]; + #endif + } + } + _TIFFfree(tmp); + + cp = (uint8 *) cp0; + cp += cc - stride - 1; + for (count = cc; count > stride; count -= stride) + REPEAT4(stride, cp[stride] = (unsigned char)((cp[stride] - cp[0])&0xff); cp--) + return 1; } static int PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - TIFFPredictorState *sp = PredictorState(tif); + TIFFPredictorState *sp = PredictorState(tif); - assert(sp != NULL); - assert(sp->encodepfunc != NULL); - assert(sp->encoderow != NULL); + assert(sp != NULL); + assert(sp->encodepfunc != NULL); + assert(sp->encoderow != NULL); - /* XXX horizontal differencing alters user's data XXX */ - (*sp->encodepfunc)(tif, bp, cc); - return (*sp->encoderow)(tif, bp, cc, s); + /* XXX horizontal differencing alters user's data XXX */ + if( !(*sp->encodepfunc)(tif, bp, cc) ) + return 0; + return (*sp->encoderow)(tif, bp, cc, s); } static int PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s) { - static const char module[] = "PredictorEncodeTile"; - TIFFPredictorState *sp = PredictorState(tif); + static const char module[] = "PredictorEncodeTile"; + TIFFPredictorState *sp = PredictorState(tif); uint8 *working_copy; - tmsize_t cc = cc0, rowsize; - unsigned char* bp; + tmsize_t cc = cc0, rowsize; + unsigned char* bp; int result_code; - assert(sp != NULL); - assert(sp->encodepfunc != NULL); - assert(sp->encodetile != NULL); + assert(sp != NULL); + assert(sp->encodepfunc != NULL); + assert(sp->encodetile != NULL); - /* + /* * Do predictor manipulation in a working buffer to avoid altering * the callers buffer. http://trac.osgeo.org/gdal/ticket/1965 */ working_copy = (uint8*) _TIFFmalloc(cc0); if( working_copy == NULL ) { - TIFFErrorExt(tif->tif_clientdata, module, + TIFFErrorExt(tif->tif_clientdata, module, "Out of memory allocating " TIFF_SSIZE_FORMAT " byte temp buffer.", cc0 ); return 0; @@ -619,15 +730,21 @@ PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s) memcpy( working_copy, bp0, cc0 ); bp = working_copy; - rowsize = sp->rowsize; - assert(rowsize > 0); - assert((cc0%rowsize)==0); - while (cc > 0) { - (*sp->encodepfunc)(tif, bp, rowsize); - cc -= rowsize; - bp += rowsize; + rowsize = sp->rowsize; + assert(rowsize > 0); + if((cc0%rowsize)!=0) + { + TIFFErrorExt(tif->tif_clientdata, "PredictorEncodeTile", + "%s", "(cc0%rowsize)!=0"); + _TIFFfree( working_copy ); + return 0; } - result_code = (*sp->encodetile)(tif, working_copy, cc0, s); + while (cc > 0) { + (*sp->encodepfunc)(tif, bp, rowsize); + cc -= rowsize; + bp += rowsize; + } + result_code = (*sp->encodetile)(tif, working_copy, cc0, s); _TIFFfree( working_copy ); @@ -643,115 +760,115 @@ static const TIFFField predictFields[] = { static int PredictorVSetField(TIFF* tif, uint32 tag, va_list ap) { - TIFFPredictorState *sp = PredictorState(tif); + TIFFPredictorState *sp = PredictorState(tif); - assert(sp != NULL); - assert(sp->vsetparent != NULL); + assert(sp != NULL); + assert(sp->vsetparent != NULL); - switch (tag) { - case TIFFTAG_PREDICTOR: - sp->predictor = (uint16) va_arg(ap, uint16_vap); - TIFFSetFieldBit(tif, FIELD_PREDICTOR); - break; - default: - return (*sp->vsetparent)(tif, tag, ap); - } - tif->tif_flags |= TIFF_DIRTYDIRECT; - return 1; + switch (tag) { + case TIFFTAG_PREDICTOR: + sp->predictor = (uint16) va_arg(ap, uint16_vap); + TIFFSetFieldBit(tif, FIELD_PREDICTOR); + break; + default: + return (*sp->vsetparent)(tif, tag, ap); + } + tif->tif_flags |= TIFF_DIRTYDIRECT; + return 1; } static int PredictorVGetField(TIFF* tif, uint32 tag, va_list ap) { - TIFFPredictorState *sp = PredictorState(tif); + TIFFPredictorState *sp = PredictorState(tif); - assert(sp != NULL); - assert(sp->vgetparent != NULL); + assert(sp != NULL); + assert(sp->vgetparent != NULL); - switch (tag) { - case TIFFTAG_PREDICTOR: - *va_arg(ap, uint16*) = sp->predictor; - break; - default: - return (*sp->vgetparent)(tif, tag, ap); - } - return 1; + switch (tag) { + case TIFFTAG_PREDICTOR: + *va_arg(ap, uint16*) = (uint16)sp->predictor; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return 1; } static void PredictorPrintDir(TIFF* tif, FILE* fd, long flags) { - TIFFPredictorState* sp = PredictorState(tif); + TIFFPredictorState* sp = PredictorState(tif); - (void) flags; - if (TIFFFieldSet(tif,FIELD_PREDICTOR)) { - fprintf(fd, " Predictor: "); - switch (sp->predictor) { - case 1: fprintf(fd, "none "); break; - case 2: fprintf(fd, "horizontal differencing "); break; - case 3: fprintf(fd, "floating point predictor "); break; - } - fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor); - } - if (sp->printdir) - (*sp->printdir)(tif, fd, flags); + (void) flags; + if (TIFFFieldSet(tif,FIELD_PREDICTOR)) { + fprintf(fd, " Predictor: "); + switch (sp->predictor) { + case 1: fprintf(fd, "none "); break; + case 2: fprintf(fd, "horizontal differencing "); break; + case 3: fprintf(fd, "floating point predictor "); break; + } + fprintf(fd, "%d (0x%x)\n", sp->predictor, sp->predictor); + } + if (sp->printdir) + (*sp->printdir)(tif, fd, flags); } int TIFFPredictorInit(TIFF* tif) { - TIFFPredictorState* sp = PredictorState(tif); + TIFFPredictorState* sp = PredictorState(tif); - assert(sp != 0); + assert(sp != 0); - /* - * Merge codec-specific tag information. - */ - if (!_TIFFMergeFields(tif, predictFields, - TIFFArrayCount(predictFields))) { - TIFFErrorExt(tif->tif_clientdata, "TIFFPredictorInit", - "Merging Predictor codec-specific tags failed"); - return 0; - } + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, predictFields, + TIFFArrayCount(predictFields))) { + TIFFErrorExt(tif->tif_clientdata, "TIFFPredictorInit", + "Merging Predictor codec-specific tags failed"); + return 0; + } - /* - * Override parent get/set field methods. - */ - sp->vgetparent = tif->tif_tagmethods.vgetfield; - tif->tif_tagmethods.vgetfield = + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = PredictorVGetField;/* hook for predictor tag */ - sp->vsetparent = tif->tif_tagmethods.vsetfield; - tif->tif_tagmethods.vsetfield = - PredictorVSetField;/* hook for predictor tag */ - sp->printdir = tif->tif_tagmethods.printdir; - tif->tif_tagmethods.printdir = + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = + PredictorVSetField;/* hook for predictor tag */ + sp->printdir = tif->tif_tagmethods.printdir; + tif->tif_tagmethods.printdir = PredictorPrintDir; /* hook for predictor tag */ - sp->setupdecode = tif->tif_setupdecode; - tif->tif_setupdecode = PredictorSetupDecode; - sp->setupencode = tif->tif_setupencode; - tif->tif_setupencode = PredictorSetupEncode; + sp->setupdecode = tif->tif_setupdecode; + tif->tif_setupdecode = PredictorSetupDecode; + sp->setupencode = tif->tif_setupencode; + tif->tif_setupencode = PredictorSetupEncode; - sp->predictor = 1; /* default value */ - sp->encodepfunc = NULL; /* no predictor routine */ - sp->decodepfunc = NULL; /* no predictor routine */ - return 1; + sp->predictor = 1; /* default value */ + sp->encodepfunc = NULL; /* no predictor routine */ + sp->decodepfunc = NULL; /* no predictor routine */ + return 1; } int TIFFPredictorCleanup(TIFF* tif) { - TIFFPredictorState* sp = PredictorState(tif); + TIFFPredictorState* sp = PredictorState(tif); - assert(sp != 0); + assert(sp != 0); - tif->tif_tagmethods.vgetfield = sp->vgetparent; - tif->tif_tagmethods.vsetfield = sp->vsetparent; - tif->tif_tagmethods.printdir = sp->printdir; - tif->tif_setupdecode = sp->setupdecode; - tif->tif_setupencode = sp->setupencode; + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; + tif->tif_tagmethods.printdir = sp->printdir; + tif->tif_setupdecode = sp->setupdecode; + tif->tif_setupencode = sp->setupencode; - return 1; + return 1; } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_predict.h b/3rdparty/libtiff/tif_predict.h index c5622fc60b..6c68e21acb 100644 --- a/3rdparty/libtiff/tif_predict.h +++ b/3rdparty/libtiff/tif_predict.h @@ -1,4 +1,4 @@ -/* $Id: tif_predict.h,v 1.8 2010-03-10 18:56:49 bfriesen Exp $ */ +/* $Id: tif_predict.h,v 1.9 2016-10-31 17:24:26 erouault Exp $ */ /* * Copyright (c) 1995-1997 Sam Leffler @@ -30,31 +30,33 @@ * ``Library-private'' Support for the Predictor Tag */ +typedef int (*TIFFEncodeDecodeMethod)(TIFF* tif, uint8* buf, tmsize_t size); + /* * Codecs that want to support the Predictor tag must place * this structure first in their private state block so that * the predictor code can cast tif_data to find its state. */ typedef struct { - int predictor; /* predictor tag value */ - tmsize_t stride; /* sample stride over data */ - tmsize_t rowsize; /* tile/strip row size */ + int predictor; /* predictor tag value */ + tmsize_t stride; /* sample stride over data */ + tmsize_t rowsize; /* tile/strip row size */ - TIFFCodeMethod encoderow; /* parent codec encode/decode row */ - TIFFCodeMethod encodestrip; /* parent codec encode/decode strip */ - TIFFCodeMethod encodetile; /* parent codec encode/decode tile */ - TIFFPostMethod encodepfunc; /* horizontal differencer */ + TIFFCodeMethod encoderow; /* parent codec encode/decode row */ + TIFFCodeMethod encodestrip; /* parent codec encode/decode strip */ + TIFFCodeMethod encodetile; /* parent codec encode/decode tile */ + TIFFEncodeDecodeMethod encodepfunc; /* horizontal differencer */ - TIFFCodeMethod decoderow; /* parent codec encode/decode row */ - TIFFCodeMethod decodestrip; /* parent codec encode/decode strip */ - TIFFCodeMethod decodetile; /* parent codec encode/decode tile */ - TIFFPostMethod decodepfunc; /* horizontal accumulator */ + TIFFCodeMethod decoderow; /* parent codec encode/decode row */ + TIFFCodeMethod decodestrip; /* parent codec encode/decode strip */ + TIFFCodeMethod decodetile; /* parent codec encode/decode tile */ + TIFFEncodeDecodeMethod decodepfunc; /* horizontal accumulator */ - TIFFVGetMethod vgetparent; /* super-class method */ - TIFFVSetMethod vsetparent; /* super-class method */ - TIFFPrintMethod printdir; /* super-class method */ - TIFFBoolMethod setupdecode; /* super-class method */ - TIFFBoolMethod setupencode; /* super-class method */ + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ + TIFFPrintMethod printdir; /* super-class method */ + TIFFBoolMethod setupdecode; /* super-class method */ + TIFFBoolMethod setupencode; /* super-class method */ } TIFFPredictorState; #if defined(__cplusplus) diff --git a/3rdparty/libtiff/tif_print.c b/3rdparty/libtiff/tif_print.c index 4a43d790d4..24d4b98a68 100644 --- a/3rdparty/libtiff/tif_print.c +++ b/3rdparty/libtiff/tif_print.c @@ -1,26 +1,26 @@ -/* $Id: tif_print.c,v 1.59 2012-06-13 01:08:51 fwarmerdam Exp $ */ +/* $Id: tif_print.c,v 1.65 2016-11-20 22:31:22 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -35,9 +35,9 @@ #include static void -_TIFFprintAsciiBounded(FILE* fd, const char* cp, int max_chars); +_TIFFprintAsciiBounded(FILE* fd, const char* cp, size_t max_chars); -static const char *photoNames[] = { +static const char * const photoNames[] = { "min-is-white", /* PHOTOMETRIC_MINISWHITE */ "min-is-black", /* PHOTOMETRIC_MINISBLACK */ "RGB color", /* PHOTOMETRIC_RGB */ @@ -47,10 +47,12 @@ static const char *photoNames[] = { "YCbCr", /* PHOTOMETRIC_YCBCR */ "7 (0x7)", "CIE L*a*b*", /* PHOTOMETRIC_CIELAB */ + "ICC L*a*b*", /* PHOTOMETRIC_ICCLAB */ + "ITU L*a*b*" /* PHOTOMETRIC_ITULAB */ }; #define NPHOTONAMES (sizeof (photoNames) / sizeof (photoNames[0])) -static const char *orientNames[] = { +static const char * const orientNames[] = { "0 (0x0)", "row 0 top, col 0 lhs", /* ORIENTATION_TOPLEFT */ "row 0 top, col 0 rhs", /* ORIENTATION_TOPRIGHT */ @@ -65,165 +67,165 @@ static const char *orientNames[] = { static void _TIFFPrintField(FILE* fd, const TIFFField *fip, - uint32 value_count, void *raw_data) + uint32 value_count, void *raw_data) { - uint32 j; + uint32 j; + + fprintf(fd, " %s: ", fip->field_name); - fprintf(fd, " %s: ", fip->field_name); - - for(j = 0; j < value_count; j++) { - if(fip->field_type == TIFF_BYTE) - fprintf(fd, "%u", ((uint8 *) raw_data)[j]); - else if(fip->field_type == TIFF_UNDEFINED) - fprintf(fd, "0x%x", - (unsigned int) ((unsigned char *) raw_data)[j]); - else if(fip->field_type == TIFF_SBYTE) - fprintf(fd, "%d", ((int8 *) raw_data)[j]); - else if(fip->field_type == TIFF_SHORT) - fprintf(fd, "%u", ((uint16 *) raw_data)[j]); - else if(fip->field_type == TIFF_SSHORT) - fprintf(fd, "%d", ((int16 *) raw_data)[j]); - else if(fip->field_type == TIFF_LONG) - fprintf(fd, "%lu", - (unsigned long)((uint32 *) raw_data)[j]); - else if(fip->field_type == TIFF_SLONG) - fprintf(fd, "%ld", (long)((int32 *) raw_data)[j]); - else if(fip->field_type == TIFF_IFD) - fprintf(fd, "0x%lx", - (unsigned long)((uint32 *) raw_data)[j]); - else if(fip->field_type == TIFF_RATIONAL - || fip->field_type == TIFF_SRATIONAL - || fip->field_type == TIFF_FLOAT) - fprintf(fd, "%f", ((float *) raw_data)[j]); - else if(fip->field_type == TIFF_LONG8) + for(j = 0; j < value_count; j++) { + if(fip->field_type == TIFF_BYTE) + fprintf(fd, "%u", ((uint8 *) raw_data)[j]); + else if(fip->field_type == TIFF_UNDEFINED) + fprintf(fd, "0x%x", + (unsigned int) ((unsigned char *) raw_data)[j]); + else if(fip->field_type == TIFF_SBYTE) + fprintf(fd, "%d", ((int8 *) raw_data)[j]); + else if(fip->field_type == TIFF_SHORT) + fprintf(fd, "%u", ((uint16 *) raw_data)[j]); + else if(fip->field_type == TIFF_SSHORT) + fprintf(fd, "%d", ((int16 *) raw_data)[j]); + else if(fip->field_type == TIFF_LONG) + fprintf(fd, "%lu", + (unsigned long)((uint32 *) raw_data)[j]); + else if(fip->field_type == TIFF_SLONG) + fprintf(fd, "%ld", (long)((int32 *) raw_data)[j]); + else if(fip->field_type == TIFF_IFD) + fprintf(fd, "0x%lx", + (unsigned long)((uint32 *) raw_data)[j]); + else if(fip->field_type == TIFF_RATIONAL + || fip->field_type == TIFF_SRATIONAL + || fip->field_type == TIFF_FLOAT) + fprintf(fd, "%f", ((float *) raw_data)[j]); + else if(fip->field_type == TIFF_LONG8) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - fprintf(fd, "%I64u", - (unsigned __int64)((uint64 *) raw_data)[j]); + fprintf(fd, "%I64u", + (unsigned __int64)((uint64 *) raw_data)[j]); #else - fprintf(fd, "%llu", - (unsigned long long)((uint64 *) raw_data)[j]); + fprintf(fd, "%llu", + (unsigned long long)((uint64 *) raw_data)[j]); #endif - else if(fip->field_type == TIFF_SLONG8) + else if(fip->field_type == TIFF_SLONG8) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - fprintf(fd, "%I64d", (__int64)((int64 *) raw_data)[j]); + fprintf(fd, "%I64d", (__int64)((int64 *) raw_data)[j]); #else - fprintf(fd, "%lld", (long long)((int64 *) raw_data)[j]); + fprintf(fd, "%lld", (long long)((int64 *) raw_data)[j]); #endif - else if(fip->field_type == TIFF_IFD8) + else if(fip->field_type == TIFF_IFD8) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - fprintf(fd, "0x%I64x", - (unsigned __int64)((uint64 *) raw_data)[j]); + fprintf(fd, "0x%I64x", + (unsigned __int64)((uint64 *) raw_data)[j]); #else - fprintf(fd, "0x%llx", - (unsigned long long)((uint64 *) raw_data)[j]); + fprintf(fd, "0x%llx", + (unsigned long long)((uint64 *) raw_data)[j]); #endif - else if(fip->field_type == TIFF_FLOAT) - fprintf(fd, "%f", ((float *)raw_data)[j]); - else if(fip->field_type == TIFF_DOUBLE) - fprintf(fd, "%f", ((double *) raw_data)[j]); - else if(fip->field_type == TIFF_ASCII) { - fprintf(fd, "%s", (char *) raw_data); - break; - } - else { - fprintf(fd, ""); - break; - } + else if(fip->field_type == TIFF_FLOAT) + fprintf(fd, "%f", ((float *)raw_data)[j]); + else if(fip->field_type == TIFF_DOUBLE) + fprintf(fd, "%f", ((double *) raw_data)[j]); + else if(fip->field_type == TIFF_ASCII) { + fprintf(fd, "%s", (char *) raw_data); + break; + } + else { + fprintf(fd, ""); + break; + } - if(j < value_count - 1) - fprintf(fd, ","); - } + if(j < value_count - 1) + fprintf(fd, ","); + } - fprintf(fd, "\n"); + fprintf(fd, "\n"); } static int _TIFFPrettyPrintField(TIFF* tif, const TIFFField *fip, FILE* fd, uint32 tag, - uint32 value_count, void *raw_data) + uint32 value_count, void *raw_data) { (void) tif; - /* do not try to pretty print auto-defined fields */ - if (strncmp(fip->field_name,"Tag ", 4) == 0) { - return 0; - } + /* do not try to pretty print auto-defined fields */ + if (strncmp(fip->field_name,"Tag ", 4) == 0) { + return 0; + } + + switch (tag) + { + case TIFFTAG_INKSET: + if (value_count == 2 && fip->field_type == TIFF_SHORT) { + fprintf(fd, " Ink Set: "); + switch (*((uint16*)raw_data)) { + case INKSET_CMYK: + fprintf(fd, "CMYK\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + *((uint16*)raw_data), + *((uint16*)raw_data)); + break; + } + return 1; + } + return 0; - switch (tag) - { - case TIFFTAG_INKSET: - if (value_count == 2 && fip->field_type == TIFF_SHORT) { - fprintf(fd, " Ink Set: "); - switch (*((uint16*)raw_data)) { - case INKSET_CMYK: - fprintf(fd, "CMYK\n"); - break; - default: - fprintf(fd, "%u (0x%x)\n", - *((uint16*)raw_data), - *((uint16*)raw_data)); - break; - } - return 1; - } - return 0; + case TIFFTAG_DOTRANGE: + if (value_count == 2 && fip->field_type == TIFF_SHORT) { + fprintf(fd, " Dot Range: %u-%u\n", + ((uint16*)raw_data)[0], ((uint16*)raw_data)[1]); + return 1; + } + return 0; - case TIFFTAG_DOTRANGE: - if (value_count == 2 && fip->field_type == TIFF_SHORT) { - fprintf(fd, " Dot Range: %u-%u\n", - ((uint16*)raw_data)[0], ((uint16*)raw_data)[1]); - return 1; - } - return 0; + case TIFFTAG_WHITEPOINT: + if (value_count == 2 && fip->field_type == TIFF_RATIONAL) { + fprintf(fd, " White Point: %g-%g\n", + ((float *)raw_data)[0], ((float *)raw_data)[1]); + return 1; + } + return 0; - case TIFFTAG_WHITEPOINT: - if (value_count == 2 && fip->field_type == TIFF_RATIONAL) { - fprintf(fd, " White Point: %g-%g\n", - ((float *)raw_data)[0], ((float *)raw_data)[1]); - return 1; - } - return 0; + case TIFFTAG_XMLPACKET: + { + uint32 i; - case TIFFTAG_XMLPACKET: - { - uint32 i; + fprintf(fd, " XMLPacket (XMP Metadata):\n" ); + for(i = 0; i < value_count; i++) + fputc(((char *)raw_data)[i], fd); + fprintf( fd, "\n" ); + return 1; + } + case TIFFTAG_RICHTIFFIPTC: + /* + * XXX: for some weird reason RichTIFFIPTC tag + * defined as array of LONG values. + */ + fprintf(fd, + " RichTIFFIPTC Data: , %lu bytes\n", + (unsigned long) value_count * 4); + return 1; - fprintf(fd, " XMLPacket (XMP Metadata):\n" ); - for(i = 0; i < value_count; i++) - fputc(((char *)raw_data)[i], fd); - fprintf( fd, "\n" ); - return 1; - } - case TIFFTAG_RICHTIFFIPTC: - /* - * XXX: for some weird reason RichTIFFIPTC tag - * defined as array of LONG values. - */ - fprintf(fd, - " RichTIFFIPTC Data: , %lu bytes\n", - (unsigned long) value_count * 4); - return 1; + case TIFFTAG_PHOTOSHOP: + fprintf(fd, " Photoshop Data: , %lu bytes\n", + (unsigned long) value_count); + return 1; - case TIFFTAG_PHOTOSHOP: - fprintf(fd, " Photoshop Data: , %lu bytes\n", - (unsigned long) value_count); - return 1; + case TIFFTAG_ICCPROFILE: + fprintf(fd, " ICC Profile: , %lu bytes\n", + (unsigned long) value_count); + return 1; - case TIFFTAG_ICCPROFILE: - fprintf(fd, " ICC Profile: , %lu bytes\n", - (unsigned long) value_count); - return 1; + case TIFFTAG_STONITS: + if (value_count == 1 && fip->field_type == TIFF_DOUBLE) { + fprintf(fd, + " Sample to Nits conversion factor: %.4e\n", + *((double*)raw_data)); + return 1; + } + return 0; + } - case TIFFTAG_STONITS: - if (value_count == 1 && fip->field_type == TIFF_DOUBLE) { - fprintf(fd, - " Sample to Nits conversion factor: %.4e\n", - *((double*)raw_data)); - return 1; - } - return 0; - } - - return 0; + return 0; } /* @@ -233,475 +235,481 @@ _TIFFPrettyPrintField(TIFF* tif, const TIFFField *fip, FILE* fd, uint32 tag, void TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) { - TIFFDirectory *td = &tif->tif_dir; - char *sep; - uint16 i; - long l, n; + TIFFDirectory *td = &tif->tif_dir; + char *sep; + long l, n; #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - fprintf(fd, "TIFF Directory at offset 0x%I64x (%I64u)\n", - (unsigned __int64) tif->tif_diroff, - (unsigned __int64) tif->tif_diroff); + fprintf(fd, "TIFF Directory at offset 0x%I64x (%I64u)\n", + (unsigned __int64) tif->tif_diroff, + (unsigned __int64) tif->tif_diroff); #else - fprintf(fd, "TIFF Directory at offset 0x%llx (%llu)\n", - (unsigned long long) tif->tif_diroff, - (unsigned long long) tif->tif_diroff); + fprintf(fd, "TIFF Directory at offset 0x%llx (%llu)\n", + (unsigned long long) tif->tif_diroff, + (unsigned long long) tif->tif_diroff); #endif - if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) { - fprintf(fd, " Subfile Type:"); - sep = " "; - if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) { - fprintf(fd, "%sreduced-resolution image", sep); - sep = "/"; - } - if (td->td_subfiletype & FILETYPE_PAGE) { - fprintf(fd, "%smulti-page document", sep); - sep = "/"; - } - if (td->td_subfiletype & FILETYPE_MASK) - fprintf(fd, "%stransparency mask", sep); - fprintf(fd, " (%lu = 0x%lx)\n", - (long) td->td_subfiletype, (long) td->td_subfiletype); - } - if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) { - fprintf(fd, " Image Width: %lu Image Length: %lu", - (unsigned long) td->td_imagewidth, (unsigned long) td->td_imagelength); - if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH)) - fprintf(fd, " Image Depth: %lu", - (unsigned long) td->td_imagedepth); - fprintf(fd, "\n"); - } - if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) { - fprintf(fd, " Tile Width: %lu Tile Length: %lu", - (unsigned long) td->td_tilewidth, (unsigned long) td->td_tilelength); - if (TIFFFieldSet(tif,FIELD_TILEDEPTH)) - fprintf(fd, " Tile Depth: %lu", - (unsigned long) td->td_tiledepth); - fprintf(fd, "\n"); - } - if (TIFFFieldSet(tif,FIELD_RESOLUTION)) { - fprintf(fd, " Resolution: %g, %g", - td->td_xresolution, td->td_yresolution); - if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) { - switch (td->td_resolutionunit) { - case RESUNIT_NONE: - fprintf(fd, " (unitless)"); - break; - case RESUNIT_INCH: - fprintf(fd, " pixels/inch"); - break; - case RESUNIT_CENTIMETER: - fprintf(fd, " pixels/cm"); - break; - default: - fprintf(fd, " (unit %u = 0x%x)", - td->td_resolutionunit, - td->td_resolutionunit); - break; - } - } - fprintf(fd, "\n"); - } - if (TIFFFieldSet(tif,FIELD_POSITION)) - fprintf(fd, " Position: %g, %g\n", - td->td_xposition, td->td_yposition); - if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) - fprintf(fd, " Bits/Sample: %u\n", td->td_bitspersample); - if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) { - fprintf(fd, " Sample Format: "); - switch (td->td_sampleformat) { - case SAMPLEFORMAT_VOID: - fprintf(fd, "void\n"); - break; - case SAMPLEFORMAT_INT: - fprintf(fd, "signed integer\n"); - break; - case SAMPLEFORMAT_UINT: - fprintf(fd, "unsigned integer\n"); - break; - case SAMPLEFORMAT_IEEEFP: - fprintf(fd, "IEEE floating point\n"); - break; - case SAMPLEFORMAT_COMPLEXINT: - fprintf(fd, "complex signed integer\n"); - break; - case SAMPLEFORMAT_COMPLEXIEEEFP: - fprintf(fd, "complex IEEE floating point\n"); - break; - default: - fprintf(fd, "%u (0x%x)\n", - td->td_sampleformat, td->td_sampleformat); - break; - } - } - if (TIFFFieldSet(tif,FIELD_COMPRESSION)) { - const TIFFCodec* c = TIFFFindCODEC(td->td_compression); - fprintf(fd, " Compression Scheme: "); - if (c) - fprintf(fd, "%s\n", c->name); - else - fprintf(fd, "%u (0x%x)\n", - td->td_compression, td->td_compression); - } - if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) { - fprintf(fd, " Photometric Interpretation: "); - if (td->td_photometric < NPHOTONAMES) - fprintf(fd, "%s\n", photoNames[td->td_photometric]); - else { - switch (td->td_photometric) { - case PHOTOMETRIC_LOGL: - fprintf(fd, "CIE Log2(L)\n"); - break; - case PHOTOMETRIC_LOGLUV: - fprintf(fd, "CIE Log2(L) (u',v')\n"); - break; - default: - fprintf(fd, "%u (0x%x)\n", - td->td_photometric, td->td_photometric); - break; - } - } - } - if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) { - fprintf(fd, " Extra Samples: %u<", td->td_extrasamples); - sep = ""; - for (i = 0; i < td->td_extrasamples; i++) { - switch (td->td_sampleinfo[i]) { - case EXTRASAMPLE_UNSPECIFIED: - fprintf(fd, "%sunspecified", sep); - break; - case EXTRASAMPLE_ASSOCALPHA: - fprintf(fd, "%sassoc-alpha", sep); - break; - case EXTRASAMPLE_UNASSALPHA: - fprintf(fd, "%sunassoc-alpha", sep); - break; - default: - fprintf(fd, "%s%u (0x%x)", sep, - td->td_sampleinfo[i], td->td_sampleinfo[i]); - break; - } - sep = ", "; - } - fprintf(fd, ">\n"); - } - if (TIFFFieldSet(tif,FIELD_INKNAMES)) { - char* cp; - fprintf(fd, " Ink Names: "); - i = td->td_samplesperpixel; - sep = ""; - for (cp = td->td_inknames; - i > 0 && cp < td->td_inknames + td->td_inknameslen; - cp = strchr(cp,'\0')+1, i--) { - int max_chars = - td->td_inknameslen - (cp - td->td_inknames); - fputs(sep, fd); - _TIFFprintAsciiBounded(fd, cp, max_chars); - sep = ", "; - } + if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) { + fprintf(fd, " Subfile Type:"); + sep = " "; + if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) { + fprintf(fd, "%sreduced-resolution image", sep); + sep = "/"; + } + if (td->td_subfiletype & FILETYPE_PAGE) { + fprintf(fd, "%smulti-page document", sep); + sep = "/"; + } + if (td->td_subfiletype & FILETYPE_MASK) + fprintf(fd, "%stransparency mask", sep); + fprintf(fd, " (%lu = 0x%lx)\n", + (unsigned long) td->td_subfiletype, (long) td->td_subfiletype); + } + if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) { + fprintf(fd, " Image Width: %lu Image Length: %lu", + (unsigned long) td->td_imagewidth, (unsigned long) td->td_imagelength); + if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH)) + fprintf(fd, " Image Depth: %lu", + (unsigned long) td->td_imagedepth); + fprintf(fd, "\n"); + } + if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) { + fprintf(fd, " Tile Width: %lu Tile Length: %lu", + (unsigned long) td->td_tilewidth, (unsigned long) td->td_tilelength); + if (TIFFFieldSet(tif,FIELD_TILEDEPTH)) + fprintf(fd, " Tile Depth: %lu", + (unsigned long) td->td_tiledepth); + fprintf(fd, "\n"); + } + if (TIFFFieldSet(tif,FIELD_RESOLUTION)) { + fprintf(fd, " Resolution: %g, %g", + td->td_xresolution, td->td_yresolution); + if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) { + switch (td->td_resolutionunit) { + case RESUNIT_NONE: + fprintf(fd, " (unitless)"); + break; + case RESUNIT_INCH: + fprintf(fd, " pixels/inch"); + break; + case RESUNIT_CENTIMETER: + fprintf(fd, " pixels/cm"); + break; + default: + fprintf(fd, " (unit %u = 0x%x)", + td->td_resolutionunit, + td->td_resolutionunit); + break; + } + } + fprintf(fd, "\n"); + } + if (TIFFFieldSet(tif,FIELD_POSITION)) + fprintf(fd, " Position: %g, %g\n", + td->td_xposition, td->td_yposition); + if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE)) + fprintf(fd, " Bits/Sample: %u\n", td->td_bitspersample); + if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) { + fprintf(fd, " Sample Format: "); + switch (td->td_sampleformat) { + case SAMPLEFORMAT_VOID: + fprintf(fd, "void\n"); + break; + case SAMPLEFORMAT_INT: + fprintf(fd, "signed integer\n"); + break; + case SAMPLEFORMAT_UINT: + fprintf(fd, "unsigned integer\n"); + break; + case SAMPLEFORMAT_IEEEFP: + fprintf(fd, "IEEE floating point\n"); + break; + case SAMPLEFORMAT_COMPLEXINT: + fprintf(fd, "complex signed integer\n"); + break; + case SAMPLEFORMAT_COMPLEXIEEEFP: + fprintf(fd, "complex IEEE floating point\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_sampleformat, td->td_sampleformat); + break; + } + } + if (TIFFFieldSet(tif,FIELD_COMPRESSION)) { + const TIFFCodec* c = TIFFFindCODEC(td->td_compression); + fprintf(fd, " Compression Scheme: "); + if (c) + fprintf(fd, "%s\n", c->name); + else + fprintf(fd, "%u (0x%x)\n", + td->td_compression, td->td_compression); + } + if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) { + fprintf(fd, " Photometric Interpretation: "); + if (td->td_photometric < NPHOTONAMES) + fprintf(fd, "%s\n", photoNames[td->td_photometric]); + else { + switch (td->td_photometric) { + case PHOTOMETRIC_LOGL: + fprintf(fd, "CIE Log2(L)\n"); + break; + case PHOTOMETRIC_LOGLUV: + fprintf(fd, "CIE Log2(L) (u',v')\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_photometric, td->td_photometric); + break; + } + } + } + if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) { + uint16 i; + fprintf(fd, " Extra Samples: %u<", td->td_extrasamples); + sep = ""; + for (i = 0; i < td->td_extrasamples; i++) { + switch (td->td_sampleinfo[i]) { + case EXTRASAMPLE_UNSPECIFIED: + fprintf(fd, "%sunspecified", sep); + break; + case EXTRASAMPLE_ASSOCALPHA: + fprintf(fd, "%sassoc-alpha", sep); + break; + case EXTRASAMPLE_UNASSALPHA: + fprintf(fd, "%sunassoc-alpha", sep); + break; + default: + fprintf(fd, "%s%u (0x%x)", sep, + td->td_sampleinfo[i], td->td_sampleinfo[i]); + break; + } + sep = ", "; + } + fprintf(fd, ">\n"); + } + if (TIFFFieldSet(tif,FIELD_INKNAMES)) { + char* cp; + uint16 i; + fprintf(fd, " Ink Names: "); + i = td->td_samplesperpixel; + sep = ""; + for (cp = td->td_inknames; + i > 0 && cp < td->td_inknames + td->td_inknameslen; + cp = strchr(cp,'\0')+1, i--) { + size_t max_chars = + td->td_inknameslen - (cp - td->td_inknames); + fputs(sep, fd); + _TIFFprintAsciiBounded(fd, cp, max_chars); + sep = ", "; + } fputs("\n", fd); - } - if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) { - fprintf(fd, " Thresholding: "); - switch (td->td_threshholding) { - case THRESHHOLD_BILEVEL: - fprintf(fd, "bilevel art scan\n"); - break; - case THRESHHOLD_HALFTONE: - fprintf(fd, "halftone or dithered scan\n"); - break; - case THRESHHOLD_ERRORDIFFUSE: - fprintf(fd, "error diffused\n"); - break; - default: - fprintf(fd, "%u (0x%x)\n", - td->td_threshholding, td->td_threshholding); - break; - } - } - if (TIFFFieldSet(tif,FIELD_FILLORDER)) { - fprintf(fd, " FillOrder: "); - switch (td->td_fillorder) { - case FILLORDER_MSB2LSB: - fprintf(fd, "msb-to-lsb\n"); - break; - case FILLORDER_LSB2MSB: - fprintf(fd, "lsb-to-msb\n"); - break; - default: - fprintf(fd, "%u (0x%x)\n", - td->td_fillorder, td->td_fillorder); - break; - } - } - if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING)) + } + if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) { + fprintf(fd, " Thresholding: "); + switch (td->td_threshholding) { + case THRESHHOLD_BILEVEL: + fprintf(fd, "bilevel art scan\n"); + break; + case THRESHHOLD_HALFTONE: + fprintf(fd, "halftone or dithered scan\n"); + break; + case THRESHHOLD_ERRORDIFFUSE: + fprintf(fd, "error diffused\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_threshholding, td->td_threshholding); + break; + } + } + if (TIFFFieldSet(tif,FIELD_FILLORDER)) { + fprintf(fd, " FillOrder: "); + switch (td->td_fillorder) { + case FILLORDER_MSB2LSB: + fprintf(fd, "msb-to-lsb\n"); + break; + case FILLORDER_LSB2MSB: + fprintf(fd, "lsb-to-msb\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_fillorder, td->td_fillorder); + break; + } + } + if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING)) { - fprintf(fd, " YCbCr Subsampling: %u, %u\n", - td->td_ycbcrsubsampling[0], td->td_ycbcrsubsampling[1] ); - } - if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) { - fprintf(fd, " YCbCr Positioning: "); - switch (td->td_ycbcrpositioning) { - case YCBCRPOSITION_CENTERED: - fprintf(fd, "centered\n"); - break; - case YCBCRPOSITION_COSITED: - fprintf(fd, "cosited\n"); - break; - default: - fprintf(fd, "%u (0x%x)\n", - td->td_ycbcrpositioning, td->td_ycbcrpositioning); - break; - } - } - if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS)) - fprintf(fd, " Halftone Hints: light %u dark %u\n", - td->td_halftonehints[0], td->td_halftonehints[1]); - if (TIFFFieldSet(tif,FIELD_ORIENTATION)) { - fprintf(fd, " Orientation: "); - if (td->td_orientation < NORIENTNAMES) - fprintf(fd, "%s\n", orientNames[td->td_orientation]); - else - fprintf(fd, "%u (0x%x)\n", - td->td_orientation, td->td_orientation); - } - if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) - fprintf(fd, " Samples/Pixel: %u\n", td->td_samplesperpixel); - if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) { - fprintf(fd, " Rows/Strip: "); - if (td->td_rowsperstrip == (uint32) -1) - fprintf(fd, "(infinite)\n"); - else - fprintf(fd, "%lu\n", (unsigned long) td->td_rowsperstrip); - } - if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE)) - fprintf(fd, " Min Sample Value: %u\n", td->td_minsamplevalue); - if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) - fprintf(fd, " Max Sample Value: %u\n", td->td_maxsamplevalue); - if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) { - int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1; - fprintf(fd, " SMin Sample Value:"); - for (i = 0; i < count; ++i) - fprintf(fd, " %g", td->td_sminsamplevalue[i]); - fprintf(fd, "\n"); - } - if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) { - int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1; - fprintf(fd, " SMax Sample Value:"); - for (i = 0; i < count; ++i) - fprintf(fd, " %g", td->td_smaxsamplevalue[i]); - fprintf(fd, "\n"); - } - if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) { - fprintf(fd, " Planar Configuration: "); - switch (td->td_planarconfig) { - case PLANARCONFIG_CONTIG: - fprintf(fd, "single image plane\n"); - break; - case PLANARCONFIG_SEPARATE: - fprintf(fd, "separate image planes\n"); - break; - default: - fprintf(fd, "%u (0x%x)\n", - td->td_planarconfig, td->td_planarconfig); - break; - } - } - if (TIFFFieldSet(tif,FIELD_PAGENUMBER)) - fprintf(fd, " Page Number: %u-%u\n", - td->td_pagenumber[0], td->td_pagenumber[1]); - if (TIFFFieldSet(tif,FIELD_COLORMAP)) { - fprintf(fd, " Color Map: "); - if (flags & TIFFPRINT_COLORMAP) { - fprintf(fd, "\n"); - n = 1L<td_bitspersample; - for (l = 0; l < n; l++) - fprintf(fd, " %5lu: %5u %5u %5u\n", - l, - td->td_colormap[0][l], - td->td_colormap[1][l], - td->td_colormap[2][l]); - } else - fprintf(fd, "(present)\n"); - } - if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) { - fprintf(fd, " Reference Black/White:\n"); - for (i = 0; i < 3; i++) - fprintf(fd, " %2d: %5g %5g\n", i, - td->td_refblackwhite[2*i+0], - td->td_refblackwhite[2*i+1]); - } - if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) { - fprintf(fd, " Transfer Function: "); - if (flags & TIFFPRINT_CURVES) { - fprintf(fd, "\n"); - n = 1L<td_bitspersample; - for (l = 0; l < n; l++) { - fprintf(fd, " %2lu: %5u", - l, td->td_transferfunction[0][l]); - for (i = 1; i < td->td_samplesperpixel; i++) - fprintf(fd, " %5u", - td->td_transferfunction[i][l]); - fputc('\n', fd); - } - } else - fprintf(fd, "(present)\n"); - } - if (TIFFFieldSet(tif, FIELD_SUBIFD) && (td->td_subifd)) { - fprintf(fd, " SubIFD Offsets:"); - for (i = 0; i < td->td_nsubifd; i++) + fprintf(fd, " YCbCr Subsampling: %u, %u\n", + td->td_ycbcrsubsampling[0], td->td_ycbcrsubsampling[1] ); + } + if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) { + fprintf(fd, " YCbCr Positioning: "); + switch (td->td_ycbcrpositioning) { + case YCBCRPOSITION_CENTERED: + fprintf(fd, "centered\n"); + break; + case YCBCRPOSITION_COSITED: + fprintf(fd, "cosited\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_ycbcrpositioning, td->td_ycbcrpositioning); + break; + } + } + if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS)) + fprintf(fd, " Halftone Hints: light %u dark %u\n", + td->td_halftonehints[0], td->td_halftonehints[1]); + if (TIFFFieldSet(tif,FIELD_ORIENTATION)) { + fprintf(fd, " Orientation: "); + if (td->td_orientation < NORIENTNAMES) + fprintf(fd, "%s\n", orientNames[td->td_orientation]); + else + fprintf(fd, "%u (0x%x)\n", + td->td_orientation, td->td_orientation); + } + if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL)) + fprintf(fd, " Samples/Pixel: %u\n", td->td_samplesperpixel); + if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) { + fprintf(fd, " Rows/Strip: "); + if (td->td_rowsperstrip == (uint32) -1) + fprintf(fd, "(infinite)\n"); + else + fprintf(fd, "%lu\n", (unsigned long) td->td_rowsperstrip); + } + if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE)) + fprintf(fd, " Min Sample Value: %u\n", td->td_minsamplevalue); + if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE)) + fprintf(fd, " Max Sample Value: %u\n", td->td_maxsamplevalue); + if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) { + int i; + int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1; + fprintf(fd, " SMin Sample Value:"); + for (i = 0; i < count; ++i) + fprintf(fd, " %g", td->td_sminsamplevalue[i]); + fprintf(fd, "\n"); + } + if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) { + int i; + int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1; + fprintf(fd, " SMax Sample Value:"); + for (i = 0; i < count; ++i) + fprintf(fd, " %g", td->td_smaxsamplevalue[i]); + fprintf(fd, "\n"); + } + if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) { + fprintf(fd, " Planar Configuration: "); + switch (td->td_planarconfig) { + case PLANARCONFIG_CONTIG: + fprintf(fd, "single image plane\n"); + break; + case PLANARCONFIG_SEPARATE: + fprintf(fd, "separate image planes\n"); + break; + default: + fprintf(fd, "%u (0x%x)\n", + td->td_planarconfig, td->td_planarconfig); + break; + } + } + if (TIFFFieldSet(tif,FIELD_PAGENUMBER)) + fprintf(fd, " Page Number: %u-%u\n", + td->td_pagenumber[0], td->td_pagenumber[1]); + if (TIFFFieldSet(tif,FIELD_COLORMAP)) { + fprintf(fd, " Color Map: "); + if (flags & TIFFPRINT_COLORMAP) { + fprintf(fd, "\n"); + n = 1L<td_bitspersample; + for (l = 0; l < n; l++) + fprintf(fd, " %5ld: %5u %5u %5u\n", + l, + td->td_colormap[0][l], + td->td_colormap[1][l], + td->td_colormap[2][l]); + } else + fprintf(fd, "(present)\n"); + } + if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) { + int i; + fprintf(fd, " Reference Black/White:\n"); + for (i = 0; i < 3; i++) + fprintf(fd, " %2d: %5g %5g\n", i, + td->td_refblackwhite[2*i+0], + td->td_refblackwhite[2*i+1]); + } + if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) { + fprintf(fd, " Transfer Function: "); + if (flags & TIFFPRINT_CURVES) { + fprintf(fd, "\n"); + n = 1L<td_bitspersample; + for (l = 0; l < n; l++) { + uint16 i; + fprintf(fd, " %2ld: %5u", + l, td->td_transferfunction[0][l]); + for (i = 1; i < td->td_samplesperpixel; i++) + fprintf(fd, " %5u", + td->td_transferfunction[i][l]); + fputc('\n', fd); + } + } else + fprintf(fd, "(present)\n"); + } + if (TIFFFieldSet(tif, FIELD_SUBIFD) && (td->td_subifd)) { + uint16 i; + fprintf(fd, " SubIFD Offsets:"); + for (i = 0; i < td->td_nsubifd; i++) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - fprintf(fd, " %5I64u", - (unsigned __int64) td->td_subifd[i]); + fprintf(fd, " %5I64u", + (unsigned __int64) td->td_subifd[i]); #else - fprintf(fd, " %5llu", - (unsigned long long) td->td_subifd[i]); + fprintf(fd, " %5llu", + (unsigned long long) td->td_subifd[i]); #endif - fputc('\n', fd); - } + fputc('\n', fd); + } - /* - ** Custom tag support. - */ - { - int i; - short count; + /* + ** Custom tag support. + */ + { + int i; + short count; - count = (short) TIFFGetTagListCount(tif); - for(i = 0; i < count; i++) { - uint32 tag = TIFFGetTagListEntry(tif, i); - const TIFFField *fip; - uint32 value_count; - int mem_alloc = 0; - void *raw_data; + count = (short) TIFFGetTagListCount(tif); + for(i = 0; i < count; i++) { + uint32 tag = TIFFGetTagListEntry(tif, i); + const TIFFField *fip; + uint32 value_count; + int mem_alloc = 0; + void *raw_data; - fip = TIFFFieldWithTag(tif, tag); - if(fip == NULL) - continue; + fip = TIFFFieldWithTag(tif, tag); + if(fip == NULL) + continue; - if(fip->field_passcount) { - if (fip->field_readcount == TIFF_VARIABLE2 ) { - if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) - continue; - } else if (fip->field_readcount == TIFF_VARIABLE2 ) { - uint16 small_value_count; - if(TIFFGetField(tif, tag, &small_value_count, &raw_data) != 1) - continue; - value_count = small_value_count; - } else { - assert (fip->field_readcount == TIFF_VARIABLE - || fip->field_readcount == TIFF_VARIABLE2); - continue; - } - } else { - if (fip->field_readcount == TIFF_VARIABLE - || fip->field_readcount == TIFF_VARIABLE2) - value_count = 1; - else if (fip->field_readcount == TIFF_SPP) - value_count = td->td_samplesperpixel; - else - value_count = fip->field_readcount; - if (fip->field_tag == TIFFTAG_DOTRANGE - && strcmp(fip->field_name,"DotRange") == 0) { - /* TODO: This is an evil exception and should not have been - handled this way ... likely best if we move it into - the directory structure with an explicit field in - libtiff 4.1 and assign it a FIELD_ value */ - static uint16 dotrange[2]; - raw_data = dotrange; - TIFFGetField(tif, tag, dotrange+0, dotrange+1); - } else if (fip->field_type == TIFF_ASCII - || fip->field_readcount == TIFF_VARIABLE - || fip->field_readcount == TIFF_VARIABLE2 - || fip->field_readcount == TIFF_SPP - || value_count > 1) { - if(TIFFGetField(tif, tag, &raw_data) != 1) - continue; - } else { - raw_data = _TIFFmalloc( - _TIFFDataSize(fip->field_type) - * value_count); - mem_alloc = 1; - if(TIFFGetField(tif, tag, raw_data) != 1) { - _TIFFfree(raw_data); - continue; - } - } - } + if(fip->field_passcount) { + if (fip->field_readcount == TIFF_VARIABLE2 ) { + if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) + continue; + } else if (fip->field_readcount == TIFF_VARIABLE ) { + uint16 small_value_count; + if(TIFFGetField(tif, tag, &small_value_count, &raw_data) != 1) + continue; + value_count = small_value_count; + } else { + assert (fip->field_readcount == TIFF_VARIABLE + || fip->field_readcount == TIFF_VARIABLE2); + continue; + } + } else { + if (fip->field_readcount == TIFF_VARIABLE + || fip->field_readcount == TIFF_VARIABLE2) + value_count = 1; + else if (fip->field_readcount == TIFF_SPP) + value_count = td->td_samplesperpixel; + else + value_count = fip->field_readcount; + if (fip->field_tag == TIFFTAG_DOTRANGE + && strcmp(fip->field_name,"DotRange") == 0) { + /* TODO: This is an evil exception and should not have been + handled this way ... likely best if we move it into + the directory structure with an explicit field in + libtiff 4.1 and assign it a FIELD_ value */ + static uint16 dotrange[2]; + raw_data = dotrange; + TIFFGetField(tif, tag, dotrange+0, dotrange+1); + } else if (fip->field_type == TIFF_ASCII + || fip->field_readcount == TIFF_VARIABLE + || fip->field_readcount == TIFF_VARIABLE2 + || fip->field_readcount == TIFF_SPP + || value_count > 1) { + if(TIFFGetField(tif, tag, &raw_data) != 1) + continue; + } else { + raw_data = _TIFFmalloc( + _TIFFDataSize(fip->field_type) + * value_count); + mem_alloc = 1; + if(TIFFGetField(tif, tag, raw_data) != 1) { + _TIFFfree(raw_data); + continue; + } + } + } - /* - * Catch the tags which needs to be specially handled - * and pretty print them. If tag not handled in - * _TIFFPrettyPrintField() fall down and print it as - * any other tag. - */ - if (!_TIFFPrettyPrintField(tif, fip, fd, tag, value_count, raw_data)) - _TIFFPrintField(fd, fip, value_count, raw_data); + /* + * Catch the tags which needs to be specially handled + * and pretty print them. If tag not handled in + * _TIFFPrettyPrintField() fall down and print it as + * any other tag. + */ + if (!_TIFFPrettyPrintField(tif, fip, fd, tag, value_count, raw_data)) + _TIFFPrintField(fd, fip, value_count, raw_data); - if(mem_alloc) - _TIFFfree(raw_data); - } - } - - if (tif->tif_tagmethods.printdir) - (*tif->tif_tagmethods.printdir)(tif, fd, flags); + if(mem_alloc) + _TIFFfree(raw_data); + } + } + + if (tif->tif_tagmethods.printdir) + (*tif->tif_tagmethods.printdir)(tif, fd, flags); _TIFFFillStriles( tif ); + + if ((flags & TIFFPRINT_STRIPS) && + TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { + uint32 s; - if ((flags & TIFFPRINT_STRIPS) && - TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { - uint32 s; - - fprintf(fd, " %lu %s:\n", - (long) td->td_nstrips, - isTiled(tif) ? "Tiles" : "Strips"); - for (s = 0; s < td->td_nstrips; s++) + fprintf(fd, " %lu %s:\n", + (unsigned long) td->td_nstrips, + isTiled(tif) ? "Tiles" : "Strips"); + for (s = 0; s < td->td_nstrips; s++) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - fprintf(fd, " %3lu: [%8I64u, %8I64u]\n", - (unsigned long) s, - (unsigned __int64) td->td_stripoffset[s], - (unsigned __int64) td->td_stripbytecount[s]); + fprintf(fd, " %3lu: [%8I64u, %8I64u]\n", + (unsigned long) s, + (unsigned __int64) td->td_stripoffset[s], + (unsigned __int64) td->td_stripbytecount[s]); #else - fprintf(fd, " %3lu: [%8llu, %8llu]\n", - (unsigned long) s, - (unsigned long long) td->td_stripoffset[s], - (unsigned long long) td->td_stripbytecount[s]); + fprintf(fd, " %3lu: [%8llu, %8llu]\n", + (unsigned long) s, + (unsigned long long) td->td_stripoffset[s], + (unsigned long long) td->td_stripbytecount[s]); #endif - } + } } void _TIFFprintAscii(FILE* fd, const char* cp) { - _TIFFprintAsciiBounded( fd, cp, strlen(cp)); + _TIFFprintAsciiBounded( fd, cp, strlen(cp)); } static void -_TIFFprintAsciiBounded(FILE* fd, const char* cp, int max_chars) +_TIFFprintAsciiBounded(FILE* fd, const char* cp, size_t max_chars) { - for (; max_chars > 0 && *cp != '\0'; cp++, max_chars--) { - const char* tp; + for (; max_chars > 0 && *cp != '\0'; cp++, max_chars--) { + const char* tp; - if (isprint((int)*cp)) { - fputc(*cp, fd); - continue; - } - for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++) - if (*tp++ == *cp) - break; - if (*tp) - fprintf(fd, "\\%c", *tp); - else - fprintf(fd, "\\%03o", *cp & 0xff); - } + if (isprint((int)*cp)) { + fputc(*cp, fd); + continue; + } + for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++) + if (*tp++ == *cp) + break; + if (*tp) + fprintf(fd, "\\%c", *tp); + else + fprintf(fd, "\\%03o", *cp & 0xff); + } } void _TIFFprintAsciiTag(FILE* fd, const char* name, const char* value) { - fprintf(fd, " %s: \"", name); - _TIFFprintAscii(fd, value); - fprintf(fd, "\"\n"); + fprintf(fd, " %s: \"", name); + _TIFFprintAscii(fd, value); + fprintf(fd, "\"\n"); } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_read.c b/3rdparty/libtiff/tif_read.c index 34647fb59e..2ba985a749 100644 --- a/3rdparty/libtiff/tif_read.c +++ b/3rdparty/libtiff/tif_read.c @@ -1,26 +1,26 @@ -/* $Id: tif_read.c,v 1.40 2012-06-01 00:55:09 fwarmerdam Exp $ */ +/* $Id: tif_read.c,v 1.66 2017-11-17 20:21:00 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -31,6 +31,9 @@ #include "tiffiop.h" #include +#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0)) +#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1) + int TIFFFillStrip(TIFF* tif, uint32 strip); int TIFFFillTile(TIFF* tif, uint32 tile); static int TIFFStartStrip(TIFF* tif, uint32 strip); @@ -38,33 +41,158 @@ static int TIFFStartTile(TIFF* tif, uint32 tile); static int TIFFCheckRead(TIFF*, int); static tmsize_t TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,const char* module); +static tmsize_t +TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module); #define NOSTRIP ((uint32)(-1)) /* undefined state */ #define NOTILE ((uint32)(-1)) /* undefined state */ +#define INITIAL_THRESHOLD (1024 * 1024) +#define THRESHOLD_MULTIPLIER 10 +#define MAX_THRESHOLD (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * INITIAL_THRESHOLD) + +/* Read 'size' bytes in tif_rawdata buffer starting at offset 'rawdata_offset' + * Returns 1 in case of success, 0 otherwise. */ +static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size, + tmsize_t rawdata_offset, + int is_strip, uint32 strip_or_tile, + const char* module ) +{ +#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8 + tmsize_t threshold = INITIAL_THRESHOLD; +#endif + tmsize_t already_read = 0; + + /* On 64 bit processes, read first a maximum of 1 MB, then 10 MB, etc */ + /* so as to avoid allocating too much memory in case the file is too */ + /* short. We could ask for the file size, but this might be */ + /* expensive with some I/O layers (think of reading a gzipped file) */ + /* Restrict to 64 bit processes, so as to avoid reallocs() */ + /* on 32 bit processes where virtual memory is scarce. */ + while( already_read < size ) + { + tmsize_t bytes_read; + tmsize_t to_read = size - already_read; +#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8 + if( to_read >= threshold && threshold < MAX_THRESHOLD && + already_read + to_read + rawdata_offset > tif->tif_rawdatasize ) + { + to_read = threshold; + threshold *= THRESHOLD_MULTIPLIER; + } +#endif + if (already_read + to_read + rawdata_offset > tif->tif_rawdatasize) { + uint8* new_rawdata; + assert((tif->tif_flags & TIFF_MYBUFFER) != 0); + tif->tif_rawdatasize = (tmsize_t)TIFFroundup_64( + (uint64)already_read + to_read + rawdata_offset, 1024); + if (tif->tif_rawdatasize==0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Invalid buffer size"); + return 0; + } + new_rawdata = (uint8*) _TIFFrealloc( + tif->tif_rawdata, tif->tif_rawdatasize); + if( new_rawdata == 0 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "No space for data buffer at scanline %lu", + (unsigned long) tif->tif_row); + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = 0; + tif->tif_rawdatasize = 0; + return 0; + } + tif->tif_rawdata = new_rawdata; + } + + bytes_read = TIFFReadFile(tif, + tif->tif_rawdata + rawdata_offset + already_read, to_read); + already_read += bytes_read; + if (bytes_read != to_read) { + memset( tif->tif_rawdata + rawdata_offset + already_read, 0, + tif->tif_rawdatasize - rawdata_offset - already_read ); +#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) + if( is_strip ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at scanline %lu; got %I64u bytes, " + "expected %I64u", + (unsigned long) tif->tif_row, + (unsigned __int64) already_read, + (unsigned __int64) size); + } + else + { + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at row %lu, col %lu, tile %lu; " + "got %I64u bytes, expected %I64u", + (unsigned long) tif->tif_row, + (unsigned long) tif->tif_col, + (unsigned long) strip_or_tile, + (unsigned __int64) already_read, + (unsigned __int64) size); + } +#else + if( is_strip ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at scanline %lu; got %llu bytes, " + "expected %llu", + (unsigned long) tif->tif_row, + (unsigned long long) already_read, + (unsigned long long) size); + } + else + { + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at row %lu, col %lu, tile %lu; " + "got %llu bytes, expected %llu", + (unsigned long) tif->tif_row, + (unsigned long) tif->tif_col, + (unsigned long) strip_or_tile, + (unsigned long long) already_read, + (unsigned long long) size); + } +#endif + return 0; + } + } + return 1; +} + + static int TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) { - static const char module[] = "TIFFFillStripPartial"; - register TIFFDirectory *td = &tif->tif_dir; - uint64 unused_data; + static const char module[] = "TIFFFillStripPartial"; + register TIFFDirectory *td = &tif->tif_dir; + tmsize_t unused_data; uint64 read_offset; - tmsize_t cc, to_read; - tmsize_t bytecountm; - + tmsize_t to_read; + tmsize_t read_ahead_mod; + /* tmsize_t bytecountm; */ + if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; - + /* * Expand raw data buffer, if needed, to hold data * strip coming from file (perhaps should set upper * bound on the size of a buffer we'll use?). */ - bytecountm=(tmsize_t) td->td_stripbytecount[strip]; - if (read_ahead*2 > tif->tif_rawdatasize) { - assert( restart ); + /* bytecountm=(tmsize_t) td->td_stripbytecount[strip]; */ + /* Not completely sure where the * 2 comes from, but probably for */ + /* an exponentional growth strategy of tif_rawdatasize */ + if( read_ahead < TIFF_TMSIZE_T_MAX / 2 ) + read_ahead_mod = read_ahead * 2; + else + read_ahead_mod = read_ahead; + if (read_ahead_mod > tif->tif_rawdatasize) { + assert( restart ); + tif->tif_curstrip = NOSTRIP; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, @@ -72,8 +200,6 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) (unsigned long) strip); return (0); } - if (!TIFFReadBufferSetup(tif, 0, read_ahead*2)) - return (0); } if( restart ) @@ -90,10 +216,10 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) unused_data = tif->tif_rawdataloaded - (tif->tif_rawcp - tif->tif_rawdata); else unused_data = 0; - + if( unused_data > 0 ) { - assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); + assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); memmove( tif->tif_rawdata, tif->tif_rawcp, unused_data ); } @@ -113,53 +239,67 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) /* ** How much do we want to read? */ - to_read = tif->tif_rawdatasize - unused_data; - if( (uint64) to_read > td->td_stripbytecount[strip] + if( read_ahead_mod > tif->tif_rawdatasize ) + to_read = read_ahead_mod - unused_data; + else + to_read = tif->tif_rawdatasize - unused_data; + if( (uint64) to_read > td->td_stripbytecount[strip] - tif->tif_rawdataoff - tif->tif_rawdataloaded ) { - to_read = td->td_stripbytecount[strip] + to_read = (tmsize_t) td->td_stripbytecount[strip] - tif->tif_rawdataoff - tif->tif_rawdataloaded; } - assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); - cc = TIFFReadFile(tif, tif->tif_rawdata + unused_data, to_read); - - if (cc != to_read) { -#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "Read error at scanline %lu; got %I64u bytes, expected %I64u", - (unsigned long) tif->tif_row, - (unsigned __int64) cc, - (unsigned __int64) to_read); -#else - TIFFErrorExt(tif->tif_clientdata, module, - "Read error at scanline %lu; got %llu bytes, expected %llu", - (unsigned long) tif->tif_row, - (unsigned long long) cc, - (unsigned long long) to_read); -#endif + assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); + if( !TIFFReadAndRealloc( tif, to_read, unused_data, + 1, /* is_strip */ + 0, /* strip_or_tile */ + module) ) + { return 0; } tif->tif_rawdataoff = tif->tif_rawdataoff + tif->tif_rawdataloaded - unused_data ; tif->tif_rawdataloaded = unused_data + to_read; + tif->tif_rawcc = tif->tif_rawdataloaded; tif->tif_rawcp = tif->tif_rawdata; - + if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) { - assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); + assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); TIFFReverseBits(tif->tif_rawdata + unused_data, to_read ); - } + } /* ** When starting a strip from the beginning we need to ** restart the decoder. */ if( restart ) - return TIFFStartStrip(tif, strip); + { + +#ifdef JPEG_SUPPORT + /* A bit messy since breaks the codec abstraction. Ultimately */ + /* there should be a function pointer for that, but it seems */ + /* only JPEG is affected. */ + /* For JPEG, if there are multiple scans (can generally be known */ + /* with the read_ahead used), we need to read the whole strip */ + if( tif->tif_dir.td_compression==COMPRESSION_JPEG && + (uint64)tif->tif_rawcc < td->td_stripbytecount[strip] ) + { + if( TIFFJPEGIsFullStripRequired(tif) ) + { + return TIFFFillStrip(tif, strip); + } + } +#endif + + return TIFFStartStrip(tif, strip); + } else + { return 1; + } } /* @@ -173,31 +313,31 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) static int TIFFSeek(TIFF* tif, uint32 row, uint16 sample ) { - register TIFFDirectory *td = &tif->tif_dir; - uint32 strip; + register TIFFDirectory *td = &tif->tif_dir; + uint32 strip; int whole_strip; - tmsize_t read_ahead = 0; + tmsize_t read_ahead = 0; /* ** Establish what strip we are working from. */ - if (row >= td->td_imagelength) { /* out of range */ - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "%lu: Row out of range, max %lu", - (unsigned long) row, - (unsigned long) td->td_imagelength); - return (0); - } - if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { - if (sample >= td->td_samplesperpixel) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "%lu: Sample out of range, max %lu", - (unsigned long) sample, (unsigned long) td->td_samplesperpixel); - return (0); - } - strip = (uint32)sample*td->td_stripsperimage + row/td->td_rowsperstrip; - } else - strip = row / td->td_rowsperstrip; + if (row >= td->td_imagelength) { /* out of range */ + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Row out of range, max %lu", + (unsigned long) row, + (unsigned long) td->td_imagelength); + return (0); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + if (sample >= td->td_samplesperpixel) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Sample out of range, max %lu", + (unsigned long) sample, (unsigned long) td->td_samplesperpixel); + return (0); + } + strip = (uint32)sample*td->td_stripsperimage + row/td->td_rowsperstrip; + } else + strip = row / td->td_rowsperstrip; /* * Do we want to treat this strip as one whole chunk or @@ -211,18 +351,29 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample ) #else whole_strip = 1; #endif - + if( !whole_strip ) { - read_ahead = tif->tif_scanlinesize * 16 + 5000; + /* 16 is for YCbCr mode where we may need to read 16 */ + /* lines at a time to get a decompressed line, and 5000 */ + /* is some constant value, for example for JPEG tables */ + if( tif->tif_scanlinesize < TIFF_TMSIZE_T_MAX / 16 && + tif->tif_scanlinesize * 16 < TIFF_TMSIZE_T_MAX - 5000 ) + { + read_ahead = tif->tif_scanlinesize * 16 + 5000; + } + else + { + read_ahead = tif->tif_scanlinesize; + } } /* * If we haven't loaded this strip, do so now, possibly * only reading the first part. */ - if (strip != tif->tif_curstrip) { /* different strip, refill */ - + if (strip != tif->tif_curstrip) { /* different strip, refill */ + if( whole_strip ) { if (!TIFFFillStrip(tif, strip)) @@ -233,14 +384,14 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample ) if( !TIFFFillStripPartial(tif,strip,read_ahead,1) ) return 0; } - } + } /* ** If we already have some data loaded, do we need to read some more? */ else if( !whole_strip ) { - if( ((tif->tif_rawdata + tif->tif_rawdataloaded) - tif->tif_rawcp) < read_ahead + if( ((tif->tif_rawdata + tif->tif_rawdataloaded) - tif->tif_rawcp) < read_ahead && (uint64) tif->tif_rawdataoff+tif->tif_rawdataloaded < td->td_stripbytecount[strip] ) { if( !TIFFFillStripPartial(tif,strip,read_ahead,0) ) @@ -249,14 +400,14 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample ) } if (row < tif->tif_row) { - /* - * Moving backwards within the same strip: backup - * to the start and then decode forward (below). - * - * NB: If you're planning on lots of random access within a - * strip, it's better to just read and decode the entire - * strip, and then access the decoded data in a random fashion. - */ + /* + * Moving backwards within the same strip: backup + * to the start and then decode forward (below). + * + * NB: If you're planning on lots of random access within a + * strip, it's better to just read and decode the entire + * strip, and then access the decoded data in a random fashion. + */ if( tif->tif_rawdataoff != 0 ) { @@ -268,45 +419,84 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample ) if (!TIFFStartStrip(tif, strip)) return (0); } - } - - if (row != tif->tif_row) { - /* - * Seek forward to the desired row. - */ + } + + if (row != tif->tif_row) { + /* + * Seek forward to the desired row. + */ /* TODO: Will this really work with partial buffers? */ + + if (!(*tif->tif_seek)(tif, row - tif->tif_row)) + return (0); + tif->tif_row = row; + } - if (!(*tif->tif_seek)(tif, row - tif->tif_row)) - return (0); - tif->tif_row = row; - } - - return (1); + return (1); } int TIFFReadScanline(TIFF* tif, void* buf, uint32 row, uint16 sample) { - int e; + int e; - if (!TIFFCheckRead(tif, 0)) - return (-1); - if( (e = TIFFSeek(tif, row, sample)) != 0) { - /* - * Decompress desired row into user buffer. - */ - e = (*tif->tif_decoderow) - (tif, (uint8*) buf, tif->tif_scanlinesize, sample); + if (!TIFFCheckRead(tif, 0)) + return (-1); + if( (e = TIFFSeek(tif, row, sample)) != 0) { + /* + * Decompress desired row into user buffer. + */ + e = (*tif->tif_decoderow) + (tif, (uint8*) buf, tif->tif_scanlinesize, sample); - /* we are now poised at the beginning of the next row */ - tif->tif_row = row + 1; + /* we are now poised at the beginning of the next row */ + tif->tif_row = row + 1; - if (e) - (*tif->tif_postdecode)(tif, (uint8*) buf, - tif->tif_scanlinesize); - } - return (e > 0 ? 1 : -1); + if (e) + (*tif->tif_postdecode)(tif, (uint8*) buf, + tif->tif_scanlinesize); + } + return (e > 0 ? 1 : -1); +} + +/* + * Calculate the strip size according to the number of + * rows in the strip (check for truncated last strip on any + * of the separations). + */ +static tmsize_t TIFFReadEncodedStripGetStripSize(TIFF* tif, uint32 strip, uint16* pplane) +{ + static const char module[] = "TIFFReadEncodedStrip"; + TIFFDirectory *td = &tif->tif_dir; + uint32 rowsperstrip; + uint32 stripsperplane; + uint32 stripinplane; + uint32 rows; + tmsize_t stripsize; + if (!TIFFCheckRead(tif,0)) + return((tmsize_t)(-1)); + if (strip>=td->td_nstrips) + { + TIFFErrorExt(tif->tif_clientdata,module, + "%lu: Strip out of range, max %lu",(unsigned long)strip, + (unsigned long)td->td_nstrips); + return((tmsize_t)(-1)); + } + + rowsperstrip=td->td_rowsperstrip; + if (rowsperstrip>td->td_imagelength) + rowsperstrip=td->td_imagelength; + stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip); + stripinplane=(strip%stripsperplane); + if( pplane ) *pplane=(uint16)(strip/stripsperplane); + rows=td->td_imagelength-stripinplane*rowsperstrip; + if (rows>rowsperstrip) + rows=rowsperstrip; + stripsize=TIFFVStripSize(tif,rows); + if (stripsize==0) + return((tmsize_t)(-1)); + return stripsize; } /* @@ -316,119 +506,200 @@ TIFFReadScanline(TIFF* tif, void* buf, uint32 row, uint16 sample) tmsize_t TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) { - static const char module[] = "TIFFReadEncodedStrip"; - TIFFDirectory *td = &tif->tif_dir; - uint32 rowsperstrip; - uint32 stripsperplane; - uint32 stripinplane; - uint16 plane; - uint32 rows; - tmsize_t stripsize; - if (!TIFFCheckRead(tif,0)) - return((tmsize_t)(-1)); - if (strip>=td->td_nstrips) + static const char module[] = "TIFFReadEncodedStrip"; + TIFFDirectory *td = &tif->tif_dir; + tmsize_t stripsize; + uint16 plane; + + stripsize=TIFFReadEncodedStripGetStripSize(tif, strip, &plane); + if (stripsize==((tmsize_t)(-1))) + return((tmsize_t)(-1)); + + /* shortcut to avoid an extra memcpy() */ + if( td->td_compression == COMPRESSION_NONE && + size!=(tmsize_t)(-1) && size >= stripsize && + !isMapped(tif) && + ((tif->tif_flags&TIFF_NOREADRAW)==0) ) { - TIFFErrorExt(tif->tif_clientdata,module, - "%lu: Strip out of range, max %lu",(unsigned long)strip, - (unsigned long)td->td_nstrips); - return((tmsize_t)(-1)); + if (TIFFReadRawStrip1(tif, strip, buf, stripsize, module) != stripsize) + return ((tmsize_t)(-1)); + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(buf,stripsize); + + (*tif->tif_postdecode)(tif,buf,stripsize); + return (stripsize); } - /* - * Calculate the strip size according to the number of - * rows in the strip (check for truncated last strip on any - * of the separations). - */ - rowsperstrip=td->td_rowsperstrip; - if (rowsperstrip>td->td_imagelength) - rowsperstrip=td->td_imagelength; - stripsperplane=((td->td_imagelength+rowsperstrip-1)/rowsperstrip); - stripinplane=(strip%stripsperplane); - plane=(strip/stripsperplane); - rows=td->td_imagelength-stripinplane*rowsperstrip; - if (rows>rowsperstrip) - rows=rowsperstrip; - stripsize=TIFFVStripSize(tif,rows); - if (stripsize==0) - return((tmsize_t)(-1)); - if ((size!=(tmsize_t)(-1))&&(sizetif_decodestrip)(tif,buf,stripsize,plane)<=0) + return((tmsize_t)(-1)); + (*tif->tif_postdecode)(tif,buf,stripsize); + return(stripsize); +} + +/* Variant of TIFFReadEncodedStrip() that does + * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillStrip() has + * succeeded. This avoid excessive memory allocation in case of truncated + * file. + * * calls regular TIFFReadEncodedStrip() if *buf != NULL + */ +tmsize_t +_TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, + void **buf, tmsize_t bufsizetoalloc, + tmsize_t size_to_read) +{ + tmsize_t this_stripsize; + uint16 plane; + + if( *buf != NULL ) + { + return TIFFReadEncodedStrip(tif, strip, *buf, size_to_read); + } + + this_stripsize=TIFFReadEncodedStripGetStripSize(tif, strip, &plane); + if (this_stripsize==((tmsize_t)(-1))) + return((tmsize_t)(-1)); + + if ((size_to_read!=(tmsize_t)(-1))&&(size_to_readtif_decodestrip)(tif,buf,stripsize,plane)<=0) - return((tmsize_t)(-1)); - (*tif->tif_postdecode)(tif,buf,stripsize); - return(stripsize); + return((tmsize_t)(-1)); + + *buf = _TIFFmalloc(bufsizetoalloc); + if (*buf == NULL) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); + return((tmsize_t)(-1)); + } + _TIFFmemset(*buf, 0, bufsizetoalloc); + + if ((*tif->tif_decodestrip)(tif,*buf,this_stripsize,plane)<=0) + return((tmsize_t)(-1)); + (*tif->tif_postdecode)(tif,*buf,this_stripsize); + return(this_stripsize); + + } static tmsize_t TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, const char* module) { - TIFFDirectory *td = &tif->tif_dir; + TIFFDirectory *td = &tif->tif_dir; if (!_TIFFFillStriles( tif )) return ((tmsize_t)(-1)); + + assert((tif->tif_flags&TIFF_NOREADRAW)==0); + if (!isMapped(tif)) { + tmsize_t cc; - assert((tif->tif_flags&TIFF_NOREADRAW)==0); - if (!isMapped(tif)) { - tmsize_t cc; + if (!SeekOK(tif, td->td_stripoffset[strip])) { + TIFFErrorExt(tif->tif_clientdata, module, + "Seek error at scanline %lu, strip %lu", + (unsigned long) tif->tif_row, (unsigned long) strip); + return ((tmsize_t)(-1)); + } + cc = TIFFReadFile(tif, buf, size); + if (cc != size) { +#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at scanline %lu; got %I64u bytes, expected %I64u", + (unsigned long) tif->tif_row, + (unsigned __int64) cc, + (unsigned __int64) size); +#else + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at scanline %lu; got %llu bytes, expected %llu", + (unsigned long) tif->tif_row, + (unsigned long long) cc, + (unsigned long long) size); +#endif + return ((tmsize_t)(-1)); + } + } else { + tmsize_t ma = 0; + tmsize_t n; + if ((td->td_stripoffset[strip] > (uint64)TIFF_TMSIZE_T_MAX)|| + ((ma=(tmsize_t)td->td_stripoffset[strip])>tif->tif_size)) + { + n=0; + } + else if( ma > TIFF_TMSIZE_T_MAX - size ) + { + n=0; + } + else + { + tmsize_t mb=ma+size; + if (mb>tif->tif_size) + n=tif->tif_size-ma; + else + n=size; + } + if (n!=size) { +#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at scanline %lu, strip %lu; got %I64u bytes, expected %I64u", + (unsigned long) tif->tif_row, + (unsigned long) strip, + (unsigned __int64) n, + (unsigned __int64) size); +#else + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at scanline %lu, strip %lu; got %llu bytes, expected %llu", + (unsigned long) tif->tif_row, + (unsigned long) strip, + (unsigned long long) n, + (unsigned long long) size); +#endif + return ((tmsize_t)(-1)); + } + _TIFFmemcpy(buf, tif->tif_base + ma, + size); + } + return (size); +} - if (!SeekOK(tif, td->td_stripoffset[strip])) { - TIFFErrorExt(tif->tif_clientdata, module, - "Seek error at scanline %lu, strip %lu", - (unsigned long) tif->tif_row, (unsigned long) strip); +static tmsize_t +TIFFReadRawStripOrTile2(TIFF* tif, uint32 strip_or_tile, int is_strip, + tmsize_t size, const char* module) +{ + TIFFDirectory *td = &tif->tif_dir; + + assert( !isMapped(tif) ); + assert((tif->tif_flags&TIFF_NOREADRAW)==0); + + if (!SeekOK(tif, td->td_stripoffset[strip_or_tile])) { + if( is_strip ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Seek error at scanline %lu, strip %lu", + (unsigned long) tif->tif_row, + (unsigned long) strip_or_tile); + } + else + { + TIFFErrorExt(tif->tif_clientdata, module, + "Seek error at row %lu, col %lu, tile %lu", + (unsigned long) tif->tif_row, + (unsigned long) tif->tif_col, + (unsigned long) strip_or_tile); + } return ((tmsize_t)(-1)); } - cc = TIFFReadFile(tif, buf, size); - if (cc != size) { -#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "Read error at scanline %lu; got %I64u bytes, expected %I64u", - (unsigned long) tif->tif_row, - (unsigned __int64) cc, - (unsigned __int64) size); -#else - TIFFErrorExt(tif->tif_clientdata, module, - "Read error at scanline %lu; got %llu bytes, expected %llu", - (unsigned long) tif->tif_row, - (unsigned long long) cc, - (unsigned long long) size); -#endif + + if( !TIFFReadAndRealloc( tif, size, 0, is_strip, + strip_or_tile, module ) ) + { return ((tmsize_t)(-1)); } - } else { - tmsize_t ma,mb; - tmsize_t n; - ma=(tmsize_t)td->td_stripoffset[strip]; - mb=ma+size; - if (((uint64)ma!=td->td_stripoffset[strip])||(ma>tif->tif_size)) - n=0; - else if ((mbtif->tif_size)) - n=tif->tif_size-ma; - else - n=size; - if (n!=size) { -#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "Read error at scanline %lu, strip %lu; got %I64u bytes, expected %I64u", - (unsigned long) tif->tif_row, - (unsigned long) strip, - (unsigned __int64) n, - (unsigned __int64) size); -#else - TIFFErrorExt(tif->tif_clientdata, module, - "Read error at scanline %lu, strip %lu; got %llu bytes, expected %llu", - (unsigned long) tif->tif_row, - (unsigned long) strip, - (unsigned long long) n, - (unsigned long long) size); -#endif - return ((tmsize_t)(-1)); - } - _TIFFmemcpy(buf, tif->tif_base + ma, - size); - } - return (size); + + return (size); } /* @@ -437,49 +708,49 @@ TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, tmsize_t TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) { - static const char module[] = "TIFFReadRawStrip"; - TIFFDirectory *td = &tif->tif_dir; - uint64 bytecount; - tmsize_t bytecountm; + static const char module[] = "TIFFReadRawStrip"; + TIFFDirectory *td = &tif->tif_dir; + uint64 bytecount; + tmsize_t bytecountm; - if (!TIFFCheckRead(tif, 0)) - return ((tmsize_t)(-1)); - if (strip >= td->td_nstrips) { - TIFFErrorExt(tif->tif_clientdata, module, - "%lu: Strip out of range, max %lu", - (unsigned long) strip, - (unsigned long) td->td_nstrips); - return ((tmsize_t)(-1)); - } - if (tif->tif_flags&TIFF_NOREADRAW) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Compression scheme does not support access to raw uncompressed data"); - return ((tmsize_t)(-1)); - } - bytecount = td->td_stripbytecount[strip]; - if (bytecount <= 0) { + if (!TIFFCheckRead(tif, 0)) + return ((tmsize_t)(-1)); + if (strip >= td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, module, + "%lu: Strip out of range, max %lu", + (unsigned long) strip, + (unsigned long) td->td_nstrips); + return ((tmsize_t)(-1)); + } + if (tif->tif_flags&TIFF_NOREADRAW) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Compression scheme does not support access to raw uncompressed data"); + return ((tmsize_t)(-1)); + } + bytecount = td->td_stripbytecount[strip]; + if ((int64)bytecount <= 0) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "%I64u: Invalid strip byte count, strip %lu", - (unsigned __int64) bytecount, - (unsigned long) strip); + TIFFErrorExt(tif->tif_clientdata, module, + "%I64u: Invalid strip byte count, strip %lu", + (unsigned __int64) bytecount, + (unsigned long) strip); #else - TIFFErrorExt(tif->tif_clientdata, module, - "%llu: Invalid strip byte count, strip %lu", - (unsigned long long) bytecount, - (unsigned long) strip); + TIFFErrorExt(tif->tif_clientdata, module, + "%llu: Invalid strip byte count, strip %lu", + (unsigned long long) bytecount, + (unsigned long) strip); #endif - return ((tmsize_t)(-1)); - } - bytecountm = (tmsize_t)bytecount; - if ((uint64)bytecountm!=bytecount) { - TIFFErrorExt(tif->tif_clientdata, module, "Integer overflow"); - return ((tmsize_t)(-1)); - } - if (size != (tmsize_t)(-1) && size < bytecountm) - bytecountm = size; - return (TIFFReadRawStrip1(tif, strip, buf, bytecountm, module)); + return ((tmsize_t)(-1)); + } + bytecountm = (tmsize_t)bytecount; + if ((uint64)bytecountm!=bytecount) { + TIFFErrorExt(tif->tif_clientdata, module, "Integer overflow"); + return ((tmsize_t)(-1)); + } + if (size != (tmsize_t)(-1) && size < bytecountm) + bytecountm = size; + return (TIFFReadRawStrip1(tif, strip, buf, bytecountm, module)); } /* @@ -489,139 +760,194 @@ TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) int TIFFFillStrip(TIFF* tif, uint32 strip) { - static const char module[] = "TIFFFillStrip"; - TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "TIFFFillStrip"; + TIFFDirectory *td = &tif->tif_dir; - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; + if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) + return 0; - if ((tif->tif_flags&TIFF_NOREADRAW)==0) - { - uint64 bytecount = td->td_stripbytecount[strip]; - if (bytecount <= 0) { + if ((tif->tif_flags&TIFF_NOREADRAW)==0) + { + uint64 bytecount = td->td_stripbytecount[strip]; + if ((int64)bytecount <= 0) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "Invalid strip byte count %I64u, strip %lu", - (unsigned __int64) bytecount, - (unsigned long) strip); + TIFFErrorExt(tif->tif_clientdata, module, + "Invalid strip byte count %I64u, strip %lu", + (unsigned __int64) bytecount, + (unsigned long) strip); #else - TIFFErrorExt(tif->tif_clientdata, module, - "Invalid strip byte count %llu, strip %lu", - (unsigned long long) bytecount, - (unsigned long) strip); + TIFFErrorExt(tif->tif_clientdata, module, + "Invalid strip byte count %llu, strip %lu", + (unsigned long long) bytecount, + (unsigned long) strip); #endif - return (0); - } - if (isMapped(tif) && - (isFillOrder(tif, td->td_fillorder) - || (tif->tif_flags & TIFF_NOBITREV))) { - /* - * The image is mapped into memory and we either don't - * need to flip bits or the compression routine is - * going to handle this operation itself. In this - * case, avoid copying the raw data and instead just - * reference the data from the memory mapped file - * image. This assumes that the decompression - * routines do not modify the contents of the raw data - * buffer (if they try to, the application will get a - * fault since the file is mapped read-only). - */ - if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { - _TIFFfree(tif->tif_rawdata); - tif->tif_rawdata = NULL; - tif->tif_rawdatasize = 0; - } - tif->tif_flags &= ~TIFF_MYBUFFER; - /* - * We must check for overflow, potentially causing - * an OOB read. Instead of simple - * - * td->td_stripoffset[strip]+bytecount > tif->tif_size - * - * comparison (which can overflow) we do the following - * two comparisons: - */ - if (bytecount > (uint64)tif->tif_size || - td->td_stripoffset[strip] > (uint64)tif->tif_size - bytecount) { - /* - * This error message might seem strange, but - * it's what would happen if a read were done - * instead. - */ + return (0); + } + + /* To avoid excessive memory allocations: */ + /* Byte count should normally not be larger than a number of */ + /* times the uncompressed size plus some margin */ + if( bytecount > 1024 * 1024 ) + { + /* 10 and 4096 are just values that could be adjusted. */ + /* Hopefully they are safe enough for all codecs */ + tmsize_t stripsize = TIFFStripSize(tif); + if( stripsize != 0 && + (bytecount - 4096) / 10 > (uint64)stripsize ) + { + uint64 newbytecount = (uint64)stripsize * 10 + 4096; + if( (int64)newbytecount >= 0 ) + { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - - "Read error on strip %lu; " - "got %I64u bytes, expected %I64u", - (unsigned long) strip, - (unsigned __int64) tif->tif_size - td->td_stripoffset[strip], - (unsigned __int64) bytecount); + TIFFWarningExt(tif->tif_clientdata, module, + "Too large strip byte count %I64u, strip %lu. Limiting to %I64u", + (unsigned __int64) bytecount, + (unsigned long) strip, + (unsigned __int64) newbytecount); #else - TIFFErrorExt(tif->tif_clientdata, module, - - "Read error on strip %lu; " - "got %llu bytes, expected %llu", - (unsigned long) strip, - (unsigned long long) tif->tif_size - td->td_stripoffset[strip], - (unsigned long long) bytecount); + TIFFErrorExt(tif->tif_clientdata, module, + "Too large strip byte count %llu, strip %lu. Limiting to %llu", + (unsigned long long) bytecount, + (unsigned long) strip, + (unsigned long long) newbytecount); #endif - tif->tif_curstrip = NOSTRIP; - return (0); - } - tif->tif_rawdatasize = (tmsize_t)bytecount; - tif->tif_rawdata = tif->tif_base + (tmsize_t)td->td_stripoffset[strip]; + bytecount = newbytecount; + } + } + } + + if (isMapped(tif)) { + /* + * We must check for overflow, potentially causing + * an OOB read. Instead of simple + * + * td->td_stripoffset[strip]+bytecount > tif->tif_size + * + * comparison (which can overflow) we do the following + * two comparisons: + */ + if (bytecount > (uint64)tif->tif_size || + td->td_stripoffset[strip] > (uint64)tif->tif_size - bytecount) { + /* + * This error message might seem strange, but + * it's what would happen if a read were done + * instead. + */ +#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) + TIFFErrorExt(tif->tif_clientdata, module, + + "Read error on strip %lu; " + "got %I64u bytes, expected %I64u", + (unsigned long) strip, + (unsigned __int64) tif->tif_size - td->td_stripoffset[strip], + (unsigned __int64) bytecount); +#else + TIFFErrorExt(tif->tif_clientdata, module, + + "Read error on strip %lu; " + "got %llu bytes, expected %llu", + (unsigned long) strip, + (unsigned long long) tif->tif_size - td->td_stripoffset[strip], + (unsigned long long) bytecount); +#endif + tif->tif_curstrip = NOSTRIP; + return (0); + } + } + + if (isMapped(tif) && + (isFillOrder(tif, td->td_fillorder) + || (tif->tif_flags & TIFF_NOBITREV))) { + /* + * The image is mapped into memory and we either don't + * need to flip bits or the compression routine is + * going to handle this operation itself. In this + * case, avoid copying the raw data and instead just + * reference the data from the memory mapped file + * image. This assumes that the decompression + * routines do not modify the contents of the raw data + * buffer (if they try to, the application will get a + * fault since the file is mapped read-only). + */ + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = NULL; + tif->tif_rawdatasize = 0; + } + tif->tif_flags &= ~TIFF_MYBUFFER; + tif->tif_rawdatasize = (tmsize_t)bytecount; + tif->tif_rawdata = tif->tif_base + (tmsize_t)td->td_stripoffset[strip]; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = (tmsize_t) bytecount; - /* - * When we have tif_rawdata reference directly into the memory mapped file - * we need to be pretty careful about how we use the rawdata. It is not - * a general purpose working buffer as it normally otherwise is. So we - * keep track of this fact to avoid using it improperly. - */ - tif->tif_flags |= TIFF_BUFFERMMAP; - } else { - /* - * Expand raw data buffer, if needed, to hold data - * strip coming from file (perhaps should set upper - * bound on the size of a buffer we'll use?). - */ - tmsize_t bytecountm; - bytecountm=(tmsize_t)bytecount; - if ((uint64)bytecountm!=bytecount) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); - return(0); - } - if (bytecountm > tif->tif_rawdatasize) { - tif->tif_curstrip = NOSTRIP; - if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "Data buffer too small to hold strip %lu", - (unsigned long) strip); - return (0); - } - if (!TIFFReadBufferSetup(tif, 0, bytecountm)) - return (0); - } - if (tif->tif_flags&TIFF_BUFFERMMAP) { - tif->tif_curstrip = NOSTRIP; - if (!TIFFReadBufferSetup(tif, 0, bytecountm)) - return (0); - } - if (TIFFReadRawStrip1(tif, strip, tif->tif_rawdata, - bytecountm, module) != bytecountm) - return (0); + /* + * When we have tif_rawdata reference directly into the memory mapped file + * we need to be pretty careful about how we use the rawdata. It is not + * a general purpose working buffer as it normally otherwise is. So we + * keep track of this fact to avoid using it improperly. + */ + tif->tif_flags |= TIFF_BUFFERMMAP; + } else { + /* + * Expand raw data buffer, if needed, to hold data + * strip coming from file (perhaps should set upper + * bound on the size of a buffer we'll use?). + */ + tmsize_t bytecountm; + bytecountm=(tmsize_t)bytecount; + if ((uint64)bytecountm!=bytecount) + { + TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); + return(0); + } + if (bytecountm > tif->tif_rawdatasize) { + tif->tif_curstrip = NOSTRIP; + if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Data buffer too small to hold strip %lu", + (unsigned long) strip); + return (0); + } + } + if (tif->tif_flags&TIFF_BUFFERMMAP) { + tif->tif_curstrip = NOSTRIP; + tif->tif_rawdata = NULL; + tif->tif_rawdatasize = 0; + tif->tif_flags &= ~TIFF_BUFFERMMAP; + } + + if( isMapped(tif) ) + { + if (bytecountm > tif->tif_rawdatasize && + !TIFFReadBufferSetup(tif, 0, bytecountm)) + { + return (0); + } + if (TIFFReadRawStrip1(tif, strip, tif->tif_rawdata, + bytecountm, module) != bytecountm) + { + return (0); + } + } + else + { + if (TIFFReadRawStripOrTile2(tif, strip, 1, + bytecountm, module) != bytecountm) + { + return (0); + } + } + tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = bytecountm; - - if (!isFillOrder(tif, td->td_fillorder) && - (tif->tif_flags & TIFF_NOBITREV) == 0) - TIFFReverseBits(tif->tif_rawdata, bytecountm); + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(tif->tif_rawdata, bytecountm); } - } - return (TIFFStartStrip(tif, strip)); + } + return (TIFFStartStrip(tif, strip)); } /* @@ -636,10 +962,10 @@ TIFFFillStrip(TIFF* tif, uint32 strip) tmsize_t TIFFReadTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s) { - if (!TIFFCheckRead(tif, 1) || !TIFFCheckTile(tif, x, y, z, s)) - return ((tmsize_t)(-1)); - return (TIFFReadEncodedTile(tif, - TIFFComputeTile(tif, x, y, z, s), buf, (tmsize_t)(-1))); + if (!TIFFCheckRead(tif, 1) || !TIFFCheckTile(tif, x, y, z, s)) + return ((tmsize_t)(-1)); + return (TIFFReadEncodedTile(tif, + TIFFComputeTile(tif, x, y, z, s), buf, (tmsize_t)(-1))); } /* @@ -649,26 +975,115 @@ TIFFReadTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s) tmsize_t TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size) { - static const char module[] = "TIFFReadEncodedTile"; + static const char module[] = "TIFFReadEncodedTile"; + TIFFDirectory *td = &tif->tif_dir; + tmsize_t tilesize = tif->tif_tilesize; + + if (!TIFFCheckRead(tif, 1)) + return ((tmsize_t)(-1)); + if (tile >= td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, module, + "%lu: Tile out of range, max %lu", + (unsigned long) tile, (unsigned long) td->td_nstrips); + return ((tmsize_t)(-1)); + } + + /* shortcut to avoid an extra memcpy() */ + if( td->td_compression == COMPRESSION_NONE && + size!=(tmsize_t)(-1) && size >= tilesize && + !isMapped(tif) && + ((tif->tif_flags&TIFF_NOREADRAW)==0) ) + { + if (TIFFReadRawTile1(tif, tile, buf, tilesize, module) != tilesize) + return ((tmsize_t)(-1)); + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(buf,tilesize); + + (*tif->tif_postdecode)(tif,buf,tilesize); + return (tilesize); + } + + if (size == (tmsize_t)(-1)) + size = tilesize; + else if (size > tilesize) + size = tilesize; + if (TIFFFillTile(tif, tile) && (*tif->tif_decodetile)(tif, + (uint8*) buf, size, (uint16)(tile/td->td_stripsperimage))) { + (*tif->tif_postdecode)(tif, (uint8*) buf, size); + return (size); + } else + return ((tmsize_t)(-1)); +} + +/* Variant of TIFFReadTile() that does + * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillTile() has + * succeeded. This avoid excessive memory allocation in case of truncated + * file. + * * calls regular TIFFReadEncodedTile() if *buf != NULL + */ +tmsize_t +_TIFFReadTileAndAllocBuffer(TIFF* tif, + void **buf, tmsize_t bufsizetoalloc, + uint32 x, uint32 y, uint32 z, uint16 s) +{ + if (!TIFFCheckRead(tif, 1) || !TIFFCheckTile(tif, x, y, z, s)) + return ((tmsize_t)(-1)); + return (_TIFFReadEncodedTileAndAllocBuffer(tif, + TIFFComputeTile(tif, x, y, z, s), + buf, bufsizetoalloc, + (tmsize_t)(-1))); +} + +/* Variant of TIFFReadEncodedTile() that does + * * if *buf == NULL, *buf = _TIFFmalloc(bufsizetoalloc) only after TIFFFillTile() has + * succeeded. This avoid excessive memory allocation in case of truncated + * file. + * * calls regular TIFFReadEncodedTile() if *buf != NULL + */ +tmsize_t +_TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile, + void **buf, tmsize_t bufsizetoalloc, + tmsize_t size_to_read) +{ + static const char module[] = "_TIFFReadEncodedTileAndAllocBuffer"; TIFFDirectory *td = &tif->tif_dir; tmsize_t tilesize = tif->tif_tilesize; - if (!TIFFCheckRead(tif, 1)) - return ((tmsize_t)(-1)); - if (tile >= td->td_nstrips) { - TIFFErrorExt(tif->tif_clientdata, module, - "%lu: Tile out of range, max %lu", - (unsigned long) tile, (unsigned long) td->td_nstrips); - return ((tmsize_t)(-1)); + if( *buf != NULL ) + { + return TIFFReadEncodedTile(tif, tile, *buf, size_to_read); } - if (size == (tmsize_t)(-1)) - size = tilesize; - else if (size > tilesize) - size = tilesize; - if (TIFFFillTile(tif, tile) && (*tif->tif_decodetile)(tif, - (uint8*) buf, size, (uint16)(tile/td->td_stripsperimage))) { - (*tif->tif_postdecode)(tif, (uint8*) buf, size); - return (size); + + if (!TIFFCheckRead(tif, 1)) + return ((tmsize_t)(-1)); + if (tile >= td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, module, + "%lu: Tile out of range, max %lu", + (unsigned long) tile, (unsigned long) td->td_nstrips); + return ((tmsize_t)(-1)); + } + + if (!TIFFFillTile(tif,tile)) + return((tmsize_t)(-1)); + + *buf = _TIFFmalloc(bufsizetoalloc); + if (*buf == NULL) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), + "No space for tile buffer"); + return((tmsize_t)(-1)); + } + _TIFFmemset(*buf, 0, bufsizetoalloc); + + if (size_to_read == (tmsize_t)(-1)) + size_to_read = tilesize; + else if (size_to_read > tilesize) + size_to_read = tilesize; + if( (*tif->tif_decodetile)(tif, + (uint8*) *buf, size_to_read, (uint16)(tile/td->td_stripsperimage))) { + (*tif->tif_postdecode)(tif, (uint8*) *buf, size_to_read); + return (size_to_read); } else return ((tmsize_t)(-1)); } @@ -676,76 +1091,76 @@ TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size) static tmsize_t TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module) { - TIFFDirectory *td = &tif->tif_dir; + TIFFDirectory *td = &tif->tif_dir; if (!_TIFFFillStriles( tif )) return ((tmsize_t)(-1)); - assert((tif->tif_flags&TIFF_NOREADRAW)==0); - if (!isMapped(tif)) { - tmsize_t cc; + assert((tif->tif_flags&TIFF_NOREADRAW)==0); + if (!isMapped(tif)) { + tmsize_t cc; - if (!SeekOK(tif, td->td_stripoffset[tile])) { - TIFFErrorExt(tif->tif_clientdata, module, - "Seek error at row %lu, col %lu, tile %lu", - (unsigned long) tif->tif_row, - (unsigned long) tif->tif_col, - (unsigned long) tile); - return ((tmsize_t)(-1)); - } - cc = TIFFReadFile(tif, buf, size); - if (cc != size) { + if (!SeekOK(tif, td->td_stripoffset[tile])) { + TIFFErrorExt(tif->tif_clientdata, module, + "Seek error at row %lu, col %lu, tile %lu", + (unsigned long) tif->tif_row, + (unsigned long) tif->tif_col, + (unsigned long) tile); + return ((tmsize_t)(-1)); + } + cc = TIFFReadFile(tif, buf, size); + if (cc != size) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "Read error at row %lu, col %lu; got %I64u bytes, expected %I64u", - (unsigned long) tif->tif_row, - (unsigned long) tif->tif_col, - (unsigned __int64) cc, - (unsigned __int64) size); + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at row %lu, col %lu; got %I64u bytes, expected %I64u", + (unsigned long) tif->tif_row, + (unsigned long) tif->tif_col, + (unsigned __int64) cc, + (unsigned __int64) size); #else - TIFFErrorExt(tif->tif_clientdata, module, - "Read error at row %lu, col %lu; got %llu bytes, expected %llu", - (unsigned long) tif->tif_row, - (unsigned long) tif->tif_col, - (unsigned long long) cc, - (unsigned long long) size); + TIFFErrorExt(tif->tif_clientdata, module, + "Read error at row %lu, col %lu; got %llu bytes, expected %llu", + (unsigned long) tif->tif_row, + (unsigned long) tif->tif_col, + (unsigned long long) cc, + (unsigned long long) size); #endif - return ((tmsize_t)(-1)); - } - } else { - tmsize_t ma,mb; - tmsize_t n; - ma=(tmsize_t)td->td_stripoffset[tile]; - mb=ma+size; - if (((uint64)ma!=td->td_stripoffset[tile])||(ma>tif->tif_size)) - n=0; - else if ((mbtif->tif_size)) - n=tif->tif_size-ma; - else - n=size; - if (n!=size) { + return ((tmsize_t)(-1)); + } + } else { + tmsize_t ma,mb; + tmsize_t n; + ma=(tmsize_t)td->td_stripoffset[tile]; + mb=ma+size; + if ((td->td_stripoffset[tile] > (uint64)TIFF_TMSIZE_T_MAX)||(ma>tif->tif_size)) + n=0; + else if ((mbtif->tif_size)) + n=tif->tif_size-ma; + else + n=size; + if (n!=size) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, + TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu, tile %lu; got %I64u bytes, expected %I64u", - (unsigned long) tif->tif_row, - (unsigned long) tif->tif_col, - (unsigned long) tile, - (unsigned __int64) n, - (unsigned __int64) size); + (unsigned long) tif->tif_row, + (unsigned long) tif->tif_col, + (unsigned long) tile, + (unsigned __int64) n, + (unsigned __int64) size); #else - TIFFErrorExt(tif->tif_clientdata, module, + TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu, tile %lu; got %llu bytes, expected %llu", - (unsigned long) tif->tif_row, - (unsigned long) tif->tif_col, - (unsigned long) tile, - (unsigned long long) n, - (unsigned long long) size); + (unsigned long) tif->tif_row, + (unsigned long) tif->tif_col, + (unsigned long) tile, + (unsigned long long) n, + (unsigned long long) size); #endif - return ((tmsize_t)(-1)); - } - _TIFFmemcpy(buf, tif->tif_base + ma, size); - } - return (size); + return ((tmsize_t)(-1)); + } + _TIFFmemcpy(buf, tif->tif_base + ma, size); + } + return (size); } /* @@ -754,35 +1169,35 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m tmsize_t TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size) { - static const char module[] = "TIFFReadRawTile"; - TIFFDirectory *td = &tif->tif_dir; - uint64 bytecount64; - tmsize_t bytecountm; + static const char module[] = "TIFFReadRawTile"; + TIFFDirectory *td = &tif->tif_dir; + uint64 bytecount64; + tmsize_t bytecountm; - if (!TIFFCheckRead(tif, 1)) - return ((tmsize_t)(-1)); - if (tile >= td->td_nstrips) { - TIFFErrorExt(tif->tif_clientdata, module, - "%lu: Tile out of range, max %lu", - (unsigned long) tile, (unsigned long) td->td_nstrips); - return ((tmsize_t)(-1)); - } - if (tif->tif_flags&TIFF_NOREADRAW) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Compression scheme does not support access to raw uncompressed data"); - return ((tmsize_t)(-1)); - } - bytecount64 = td->td_stripbytecount[tile]; - if (size != (tmsize_t)(-1) && (uint64)size < bytecount64) - bytecount64 = (uint64)size; - bytecountm = (tmsize_t)bytecount64; - if ((uint64)bytecountm!=bytecount64) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); - return ((tmsize_t)(-1)); - } - return (TIFFReadRawTile1(tif, tile, buf, bytecountm, module)); + if (!TIFFCheckRead(tif, 1)) + return ((tmsize_t)(-1)); + if (tile >= td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, module, + "%lu: Tile out of range, max %lu", + (unsigned long) tile, (unsigned long) td->td_nstrips); + return ((tmsize_t)(-1)); + } + if (tif->tif_flags&TIFF_NOREADRAW) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Compression scheme does not support access to raw uncompressed data"); + return ((tmsize_t)(-1)); + } + bytecount64 = td->td_stripbytecount[tile]; + if (size != (tmsize_t)(-1) && (uint64)size < bytecount64) + bytecount64 = (uint64)size; + bytecountm = (tmsize_t)bytecount64; + if ((uint64)bytecountm!=bytecount64) + { + TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); + return ((tmsize_t)(-1)); + } + return (TIFFReadRawTile1(tif, tile, buf, bytecountm, module)); } /* @@ -792,113 +1207,168 @@ TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size) int TIFFFillTile(TIFF* tif, uint32 tile) { - static const char module[] = "TIFFFillTile"; - TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "TIFFFillTile"; + TIFFDirectory *td = &tif->tif_dir; - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; + if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) + return 0; - if ((tif->tif_flags&TIFF_NOREADRAW)==0) - { - uint64 bytecount = td->td_stripbytecount[tile]; - if (bytecount <= 0) { + if ((tif->tif_flags&TIFF_NOREADRAW)==0) + { + uint64 bytecount = td->td_stripbytecount[tile]; + if ((int64)bytecount <= 0) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "%I64u: Invalid tile byte count, tile %lu", - (unsigned __int64) bytecount, - (unsigned long) tile); + TIFFErrorExt(tif->tif_clientdata, module, + "%I64u: Invalid tile byte count, tile %lu", + (unsigned __int64) bytecount, + (unsigned long) tile); #else - TIFFErrorExt(tif->tif_clientdata, module, - "%llu: Invalid tile byte count, tile %lu", - (unsigned long long) bytecount, - (unsigned long) tile); + TIFFErrorExt(tif->tif_clientdata, module, + "%llu: Invalid tile byte count, tile %lu", + (unsigned long long) bytecount, + (unsigned long) tile); #endif - return (0); - } - if (isMapped(tif) && - (isFillOrder(tif, td->td_fillorder) - || (tif->tif_flags & TIFF_NOBITREV))) { - /* - * The image is mapped into memory and we either don't - * need to flip bits or the compression routine is - * going to handle this operation itself. In this - * case, avoid copying the raw data and instead just - * reference the data from the memory mapped file - * image. This assumes that the decompression - * routines do not modify the contents of the raw data - * buffer (if they try to, the application will get a - * fault since the file is mapped read-only). - */ - if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { - _TIFFfree(tif->tif_rawdata); - tif->tif_rawdata = NULL; - tif->tif_rawdatasize = 0; - } - tif->tif_flags &= ~TIFF_MYBUFFER; - /* - * We must check for overflow, potentially causing - * an OOB read. Instead of simple - * - * td->td_stripoffset[tile]+bytecount > tif->tif_size - * - * comparison (which can overflow) we do the following - * two comparisons: - */ - if (bytecount > (uint64)tif->tif_size || - td->td_stripoffset[tile] > (uint64)tif->tif_size - bytecount) { - tif->tif_curtile = NOTILE; - return (0); - } - tif->tif_rawdatasize = (tmsize_t)bytecount; - tif->tif_rawdata = - tif->tif_base + (tmsize_t)td->td_stripoffset[tile]; + return (0); + } + + /* To avoid excessive memory allocations: */ + /* Byte count should normally not be larger than a number of */ + /* times the uncompressed size plus some margin */ + if( bytecount > 1024 * 1024 ) + { + /* 10 and 4096 are just values that could be adjusted. */ + /* Hopefully they are safe enough for all codecs */ + tmsize_t stripsize = TIFFTileSize(tif); + if( stripsize != 0 && + (bytecount - 4096) / 10 > (uint64)stripsize ) + { + uint64 newbytecount = (uint64)stripsize * 10 + 4096; + if( (int64)newbytecount >= 0 ) + { +#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) + TIFFWarningExt(tif->tif_clientdata, module, + "Too large tile byte count %I64u, tile %lu. Limiting to %I64u", + (unsigned __int64) bytecount, + (unsigned long) tile, + (unsigned __int64) newbytecount); +#else + TIFFErrorExt(tif->tif_clientdata, module, + "Too large tile byte count %llu, tile %lu. Limiting to %llu", + (unsigned long long) bytecount, + (unsigned long) tile, + (unsigned long long) newbytecount); +#endif + bytecount = newbytecount; + } + } + } + + if (isMapped(tif)) { + /* + * We must check for overflow, potentially causing + * an OOB read. Instead of simple + * + * td->td_stripoffset[tile]+bytecount > tif->tif_size + * + * comparison (which can overflow) we do the following + * two comparisons: + */ + if (bytecount > (uint64)tif->tif_size || + td->td_stripoffset[tile] > (uint64)tif->tif_size - bytecount) { + tif->tif_curtile = NOTILE; + return (0); + } + } + + if (isMapped(tif) && + (isFillOrder(tif, td->td_fillorder) + || (tif->tif_flags & TIFF_NOBITREV))) { + /* + * The image is mapped into memory and we either don't + * need to flip bits or the compression routine is + * going to handle this operation itself. In this + * case, avoid copying the raw data and instead just + * reference the data from the memory mapped file + * image. This assumes that the decompression + * routines do not modify the contents of the raw data + * buffer (if they try to, the application will get a + * fault since the file is mapped read-only). + */ + if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) { + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = NULL; + tif->tif_rawdatasize = 0; + } + tif->tif_flags &= ~TIFF_MYBUFFER; + + tif->tif_rawdatasize = (tmsize_t)bytecount; + tif->tif_rawdata = + tif->tif_base + (tmsize_t)td->td_stripoffset[tile]; tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = (tmsize_t) bytecount; - tif->tif_flags |= TIFF_BUFFERMMAP; - } else { - /* - * Expand raw data buffer, if needed, to hold data - * tile coming from file (perhaps should set upper - * bound on the size of a buffer we'll use?). - */ - tmsize_t bytecountm; - bytecountm=(tmsize_t)bytecount; - if ((uint64)bytecountm!=bytecount) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); - return(0); - } - if (bytecountm > tif->tif_rawdatasize) { - tif->tif_curtile = NOTILE; - if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "Data buffer too small to hold tile %lu", - (unsigned long) tile); - return (0); - } - if (!TIFFReadBufferSetup(tif, 0, bytecountm)) - return (0); - } - if (tif->tif_flags&TIFF_BUFFERMMAP) { - tif->tif_curtile = NOTILE; - if (!TIFFReadBufferSetup(tif, 0, bytecountm)) - return (0); - } + tif->tif_flags |= TIFF_BUFFERMMAP; + } else { + /* + * Expand raw data buffer, if needed, to hold data + * tile coming from file (perhaps should set upper + * bound on the size of a buffer we'll use?). + */ + tmsize_t bytecountm; + bytecountm=(tmsize_t)bytecount; + if ((uint64)bytecountm!=bytecount) + { + TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); + return(0); + } + if (bytecountm > tif->tif_rawdatasize) { + tif->tif_curtile = NOTILE; + if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Data buffer too small to hold tile %lu", + (unsigned long) tile); + return (0); + } + } + if (tif->tif_flags&TIFF_BUFFERMMAP) { + tif->tif_curtile = NOTILE; + tif->tif_rawdata = NULL; + tif->tif_rawdatasize = 0; + tif->tif_flags &= ~TIFF_BUFFERMMAP; + } + + if( isMapped(tif) ) + { + if (bytecountm > tif->tif_rawdatasize && + !TIFFReadBufferSetup(tif, 0, bytecountm)) + { + return (0); + } + if (TIFFReadRawTile1(tif, tile, tif->tif_rawdata, + bytecountm, module) != bytecountm) + { + return (0); + } + } + else + { + if (TIFFReadRawStripOrTile2(tif, tile, 0, + bytecountm, module) != bytecountm) + { + return (0); + } + } - if (TIFFReadRawTile1(tif, tile, tif->tif_rawdata, - bytecountm, module) != bytecountm) - return (0); tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = bytecountm; - - if (!isFillOrder(tif, td->td_fillorder) && - (tif->tif_flags & TIFF_NOBITREV) == 0) - TIFFReverseBits(tif->tif_rawdata, + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdataloaded); - } - } - return (TIFFStartTile(tif, tile)); + } + } + return (TIFFStartTile(tif, tile)); } /* @@ -913,36 +1383,41 @@ TIFFFillTile(TIFF* tif, uint32 tile) int TIFFReadBufferSetup(TIFF* tif, void* bp, tmsize_t size) { - static const char module[] = "TIFFReadBufferSetup"; + static const char module[] = "TIFFReadBufferSetup"; - assert((tif->tif_flags&TIFF_NOREADRAW)==0); - tif->tif_flags &= ~TIFF_BUFFERMMAP; + assert((tif->tif_flags&TIFF_NOREADRAW)==0); + tif->tif_flags &= ~TIFF_BUFFERMMAP; - if (tif->tif_rawdata) { - if (tif->tif_flags & TIFF_MYBUFFER) - _TIFFfree(tif->tif_rawdata); - tif->tif_rawdata = NULL; - tif->tif_rawdatasize = 0; - } - if (bp) { - tif->tif_rawdatasize = size; - tif->tif_rawdata = (uint8*) bp; - tif->tif_flags &= ~TIFF_MYBUFFER; - } else { - tif->tif_rawdatasize = (tmsize_t)TIFFroundup_64((uint64)size, 1024); - if (tif->tif_rawdatasize==0) - tif->tif_rawdatasize=(tmsize_t)(-1); - tif->tif_rawdata = (uint8*) _TIFFmalloc(tif->tif_rawdatasize); - tif->tif_flags |= TIFF_MYBUFFER; - } - if (tif->tif_rawdata == NULL) { - TIFFErrorExt(tif->tif_clientdata, module, - "No space for data buffer at scanline %lu", - (unsigned long) tif->tif_row); - tif->tif_rawdatasize = 0; - return (0); - } - return (1); + if (tif->tif_rawdata) { + if (tif->tif_flags & TIFF_MYBUFFER) + _TIFFfree(tif->tif_rawdata); + tif->tif_rawdata = NULL; + tif->tif_rawdatasize = 0; + } + if (bp) { + tif->tif_rawdatasize = size; + tif->tif_rawdata = (uint8*) bp; + tif->tif_flags &= ~TIFF_MYBUFFER; + } else { + tif->tif_rawdatasize = (tmsize_t)TIFFroundup_64((uint64)size, 1024); + if (tif->tif_rawdatasize==0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Invalid buffer size"); + return (0); + } + /* Initialize to zero to avoid uninitialized buffers in case of */ + /* short reads (http://bugzilla.maptools.org/show_bug.cgi?id=2651) */ + tif->tif_rawdata = (uint8*) _TIFFcalloc(1, tif->tif_rawdatasize); + tif->tif_flags |= TIFF_MYBUFFER; + } + if (tif->tif_rawdata == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, + "No space for data buffer at scanline %lu", + (unsigned long) tif->tif_row); + tif->tif_rawdatasize = 0; + return (0); + } + return (1); } /* @@ -952,32 +1427,35 @@ TIFFReadBufferSetup(TIFF* tif, void* bp, tmsize_t size) static int TIFFStartStrip(TIFF* tif, uint32 strip) { - TIFFDirectory *td = &tif->tif_dir; + TIFFDirectory *td = &tif->tif_dir; - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; + if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) + return 0; - if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { - if (!(*tif->tif_setupdecode)(tif)) - return (0); - tif->tif_flags |= TIFF_CODERSETUP; - } - tif->tif_curstrip = strip; - tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupdecode)(tif)) + return (0); + tif->tif_flags |= TIFF_CODERSETUP; + } + tif->tif_curstrip = strip; + tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; tif->tif_flags &= ~TIFF_BUF4WRITE; - if (tif->tif_flags&TIFF_NOREADRAW) - { - tif->tif_rawcp = NULL; - tif->tif_rawcc = 0; - } - else - { - tif->tif_rawcp = tif->tif_rawdata; - tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[strip]; - } - return ((*tif->tif_predecode)(tif, - (uint16)(strip / td->td_stripsperimage))); + if (tif->tif_flags&TIFF_NOREADRAW) + { + tif->tif_rawcp = NULL; + tif->tif_rawcc = 0; + } + else + { + tif->tif_rawcp = tif->tif_rawdata; + if( tif->tif_rawdataloaded > 0 ) + tif->tif_rawcc = tif->tif_rawdataloaded; + else + tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[strip]; + } + return ((*tif->tif_predecode)(tif, + (uint16)(strip / td->td_stripsperimage))); } /* @@ -987,52 +1465,63 @@ TIFFStartStrip(TIFF* tif, uint32 strip) static int TIFFStartTile(TIFF* tif, uint32 tile) { - TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "TIFFStartTile"; + TIFFDirectory *td = &tif->tif_dir; + uint32 howmany32; - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; + if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) + return 0; - if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { - if (!(*tif->tif_setupdecode)(tif)) - return (0); - tif->tif_flags |= TIFF_CODERSETUP; - } - tif->tif_curtile = tile; - tif->tif_row = - (tile % TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth)) * - td->td_tilelength; - tif->tif_col = - (tile % TIFFhowmany_32(td->td_imagelength, td->td_tilelength)) * - td->td_tilewidth; + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupdecode)(tif)) + return (0); + tif->tif_flags |= TIFF_CODERSETUP; + } + tif->tif_curtile = tile; + howmany32=TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth); + if (howmany32 == 0) { + TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles"); + return 0; + } + tif->tif_row = (tile % howmany32) * td->td_tilelength; + howmany32=TIFFhowmany_32(td->td_imagelength, td->td_tilelength); + if (howmany32 == 0) { + TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles"); + return 0; + } + tif->tif_col = (tile % howmany32) * td->td_tilewidth; tif->tif_flags &= ~TIFF_BUF4WRITE; - if (tif->tif_flags&TIFF_NOREADRAW) - { - tif->tif_rawcp = NULL; - tif->tif_rawcc = 0; - } - else - { - tif->tif_rawcp = tif->tif_rawdata; - tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[tile]; - } - return ((*tif->tif_predecode)(tif, - (uint16)(tile/td->td_stripsperimage))); + if (tif->tif_flags&TIFF_NOREADRAW) + { + tif->tif_rawcp = NULL; + tif->tif_rawcc = 0; + } + else + { + tif->tif_rawcp = tif->tif_rawdata; + if( tif->tif_rawdataloaded > 0 ) + tif->tif_rawcc = tif->tif_rawdataloaded; + else + tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[tile]; + } + return ((*tif->tif_predecode)(tif, + (uint16)(tile/td->td_stripsperimage))); } static int TIFFCheckRead(TIFF* tif, int tiles) { - if (tif->tif_mode == O_WRONLY) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "File not open for reading"); - return (0); - } - if (tiles ^ isTiled(tif)) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ? - "Can not read tiles from a stripped image" : - "Can not read scanlines from a tiled image"); - return (0); - } - return (1); + if (tif->tif_mode == O_WRONLY) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "File not open for reading"); + return (0); + } + if (tiles ^ isTiled(tif)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ? + "Can not read tiles from a stripped image" : + "Can not read scanlines from a tiled image"); + return (0); + } + return (1); } void diff --git a/3rdparty/libtiff/tif_strip.c b/3rdparty/libtiff/tif_strip.c index 09bd9a5685..6e9f2ef6dd 100644 --- a/3rdparty/libtiff/tif_strip.c +++ b/3rdparty/libtiff/tif_strip.c @@ -1,26 +1,26 @@ -/* $Id: tif_strip.c,v 1.35 2012-06-06 05:33:55 fwarmerdam Exp $ */ +/* $Id: tif_strip.c,v 1.38 2016-12-03 11:02:15 erouault Exp $ */ /* * Copyright (c) 1991-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -37,21 +37,21 @@ uint32 TIFFComputeStrip(TIFF* tif, uint32 row, uint16 sample) { - static const char module[] = "TIFFComputeStrip"; - TIFFDirectory *td = &tif->tif_dir; - uint32 strip; + static const char module[] = "TIFFComputeStrip"; + TIFFDirectory *td = &tif->tif_dir; + uint32 strip; - strip = row / td->td_rowsperstrip; - if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { - if (sample >= td->td_samplesperpixel) { - TIFFErrorExt(tif->tif_clientdata, module, - "%lu: Sample out of range, max %lu", - (unsigned long) sample, (unsigned long) td->td_samplesperpixel); - return (0); - } - strip += (uint32)sample*td->td_stripsperimage; - } - return (strip); + strip = row / td->td_rowsperstrip; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + if (sample >= td->td_samplesperpixel) { + TIFFErrorExt(tif->tif_clientdata, module, + "%lu: Sample out of range, max %lu", + (unsigned long) sample, (unsigned long) td->td_samplesperpixel); + return (0); + } + strip += (uint32)sample*td->td_stripsperimage; + } + return (strip); } /* @@ -60,15 +60,15 @@ TIFFComputeStrip(TIFF* tif, uint32 row, uint16 sample) uint32 TIFFNumberOfStrips(TIFF* tif) { - TIFFDirectory *td = &tif->tif_dir; - uint32 nstrips; + TIFFDirectory *td = &tif->tif_dir; + uint32 nstrips; - nstrips = (td->td_rowsperstrip == (uint32) -1 ? 1 : - TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip)); - if (td->td_planarconfig == PLANARCONFIG_SEPARATE) - nstrips = _TIFFMultiply32(tif, nstrips, (uint32)td->td_samplesperpixel, - "TIFFNumberOfStrips"); - return (nstrips); + nstrips = (td->td_rowsperstrip == (uint32) -1 ? 1 : + TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip)); + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + nstrips = _TIFFMultiply32(tif, nstrips, (uint32)td->td_samplesperpixel, + "TIFFNumberOfStrips"); + return (nstrips); } /* @@ -77,69 +77,69 @@ TIFFNumberOfStrips(TIFF* tif) uint64 TIFFVStripSize64(TIFF* tif, uint32 nrows) { - static const char module[] = "TIFFVStripSize64"; - TIFFDirectory *td = &tif->tif_dir; - if (nrows==(uint32)(-1)) - nrows=td->td_imagelength; - if ((td->td_planarconfig==PLANARCONFIG_CONTIG)&& - (td->td_photometric == PHOTOMETRIC_YCBCR)&& - (!isUpSampled(tif))) - { - /* - * Packed YCbCr data contain one Cb+Cr for every - * HorizontalSampling*VerticalSampling Y values. - * Must also roundup width and height when calculating - * since images that are not a multiple of the - * horizontal/vertical subsampling area include - * YCbCr data for the extended image. - */ - uint16 ycbcrsubsampling[2]; - uint16 samplingblock_samples; - uint32 samplingblocks_hor; - uint32 samplingblocks_ver; - uint64 samplingrow_samples; - uint64 samplingrow_size; - if(td->td_samplesperpixel!=3) - { - TIFFErrorExt(tif->tif_clientdata,module, - "Invalid td_samplesperpixel value"); - return 0; - } - TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING,ycbcrsubsampling+0, - ycbcrsubsampling+1); - if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 && ycbcrsubsampling[0] != 4) - ||(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 && ycbcrsubsampling[1] != 4)) - { - TIFFErrorExt(tif->tif_clientdata,module, - "Invalid YCbCr subsampling (%dx%d)", - ycbcrsubsampling[0], - ycbcrsubsampling[1] ); - return 0; - } - samplingblock_samples=ycbcrsubsampling[0]*ycbcrsubsampling[1]+2; - samplingblocks_hor=TIFFhowmany_32(td->td_imagewidth,ycbcrsubsampling[0]); - samplingblocks_ver=TIFFhowmany_32(nrows,ycbcrsubsampling[1]); - samplingrow_samples=_TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module); - samplingrow_size=TIFFhowmany8_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module)); - return(_TIFFMultiply64(tif,samplingrow_size,samplingblocks_ver,module)); - } - else - return(_TIFFMultiply64(tif,nrows,TIFFScanlineSize64(tif),module)); + static const char module[] = "TIFFVStripSize64"; + TIFFDirectory *td = &tif->tif_dir; + if (nrows==(uint32)(-1)) + nrows=td->td_imagelength; + if ((td->td_planarconfig==PLANARCONFIG_CONTIG)&& + (td->td_photometric == PHOTOMETRIC_YCBCR)&& + (!isUpSampled(tif))) + { + /* + * Packed YCbCr data contain one Cb+Cr for every + * HorizontalSampling*VerticalSampling Y values. + * Must also roundup width and height when calculating + * since images that are not a multiple of the + * horizontal/vertical subsampling area include + * YCbCr data for the extended image. + */ + uint16 ycbcrsubsampling[2]; + uint16 samplingblock_samples; + uint32 samplingblocks_hor; + uint32 samplingblocks_ver; + uint64 samplingrow_samples; + uint64 samplingrow_size; + if(td->td_samplesperpixel!=3) + { + TIFFErrorExt(tif->tif_clientdata,module, + "Invalid td_samplesperpixel value"); + return 0; + } + TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING,ycbcrsubsampling+0, + ycbcrsubsampling+1); + if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 && ycbcrsubsampling[0] != 4) + ||(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 && ycbcrsubsampling[1] != 4)) + { + TIFFErrorExt(tif->tif_clientdata,module, + "Invalid YCbCr subsampling (%dx%d)", + ycbcrsubsampling[0], + ycbcrsubsampling[1] ); + return 0; + } + samplingblock_samples=ycbcrsubsampling[0]*ycbcrsubsampling[1]+2; + samplingblocks_hor=TIFFhowmany_32(td->td_imagewidth,ycbcrsubsampling[0]); + samplingblocks_ver=TIFFhowmany_32(nrows,ycbcrsubsampling[1]); + samplingrow_samples=_TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module); + samplingrow_size=TIFFhowmany8_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module)); + return(_TIFFMultiply64(tif,samplingrow_size,samplingblocks_ver,module)); + } + else + return(_TIFFMultiply64(tif,nrows,TIFFScanlineSize64(tif),module)); } tmsize_t TIFFVStripSize(TIFF* tif, uint32 nrows) { - static const char module[] = "TIFFVStripSize"; - uint64 m; - tmsize_t n; - m=TIFFVStripSize64(tif,nrows); - n=(tmsize_t)m; - if ((uint64)n!=m) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); - n=0; - } - return(n); + static const char module[] = "TIFFVStripSize"; + uint64 m; + tmsize_t n; + m=TIFFVStripSize64(tif,nrows); + n=(tmsize_t)m; + if ((uint64)n!=m) + { + TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); + n=0; + } + return(n); } /* @@ -148,47 +148,47 @@ TIFFVStripSize(TIFF* tif, uint32 nrows) uint64 TIFFRawStripSize64(TIFF* tif, uint32 strip) { - static const char module[] = "TIFFRawStripSize64"; - TIFFDirectory* td = &tif->tif_dir; - uint64 bytecount = td->td_stripbytecount[strip]; + static const char module[] = "TIFFRawStripSize64"; + TIFFDirectory* td = &tif->tif_dir; + uint64 bytecount = td->td_stripbytecount[strip]; - if (bytecount == 0) - { + if (bytecount == 0) + { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "%I64u: Invalid strip byte count, strip %lu", - (unsigned __int64) bytecount, - (unsigned long) strip); + TIFFErrorExt(tif->tif_clientdata, module, + "%I64u: Invalid strip byte count, strip %lu", + (unsigned __int64) bytecount, + (unsigned long) strip); #else - TIFFErrorExt(tif->tif_clientdata, module, - "%llu: Invalid strip byte count, strip %lu", - (unsigned long long) bytecount, - (unsigned long) strip); + TIFFErrorExt(tif->tif_clientdata, module, + "%llu: Invalid strip byte count, strip %lu", + (unsigned long long) bytecount, + (unsigned long) strip); #endif - bytecount = (uint64) -1; - } + bytecount = (uint64) -1; + } - return bytecount; + return bytecount; } tmsize_t TIFFRawStripSize(TIFF* tif, uint32 strip) { - static const char module[] = "TIFFRawStripSize"; - uint64 m; - tmsize_t n; - m=TIFFRawStripSize64(tif,strip); - if (m==(uint64)(-1)) - n=(tmsize_t)(-1); - else - { - n=(tmsize_t)m; - if ((uint64)n!=m) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); - n=0; - } - } - return(n); + static const char module[] = "TIFFRawStripSize"; + uint64 m; + tmsize_t n; + m=TIFFRawStripSize64(tif,strip); + if (m==(uint64)(-1)) + n=(tmsize_t)(-1); + else + { + n=(tmsize_t)m; + if ((uint64)n!=m) + { + TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); + n=0; + } + } + return(n); } /* @@ -202,26 +202,26 @@ TIFFRawStripSize(TIFF* tif, uint32 strip) uint64 TIFFStripSize64(TIFF* tif) { - TIFFDirectory* td = &tif->tif_dir; - uint32 rps = td->td_rowsperstrip; - if (rps > td->td_imagelength) - rps = td->td_imagelength; - return (TIFFVStripSize64(tif, rps)); + TIFFDirectory* td = &tif->tif_dir; + uint32 rps = td->td_rowsperstrip; + if (rps > td->td_imagelength) + rps = td->td_imagelength; + return (TIFFVStripSize64(tif, rps)); } tmsize_t TIFFStripSize(TIFF* tif) { - static const char module[] = "TIFFStripSize"; - uint64 m; - tmsize_t n; - m=TIFFStripSize64(tif); - n=(tmsize_t)m; - if ((uint64)n!=m) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); - n=0; - } - return(n); + static const char module[] = "TIFFStripSize"; + uint64 m; + tmsize_t n; + m=TIFFStripSize64(tif); + n=(tmsize_t)m; + if ((uint64)n!=m) + { + TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); + n=0; + } + return(n); } /* @@ -233,31 +233,31 @@ TIFFStripSize(TIFF* tif) uint32 TIFFDefaultStripSize(TIFF* tif, uint32 request) { - return (*tif->tif_defstripsize)(tif, request); + return (*tif->tif_defstripsize)(tif, request); } uint32 _TIFFDefaultStripSize(TIFF* tif, uint32 s) { - if ((int32) s < 1) { - /* - * If RowsPerStrip is unspecified, try to break the - * image up into strips that are approximately - * STRIP_SIZE_DEFAULT bytes long. - */ - uint64 scanlinesize; - uint64 rows; - scanlinesize=TIFFScanlineSize64(tif); - if (scanlinesize==0) - scanlinesize=1; - rows=(uint64)STRIP_SIZE_DEFAULT/scanlinesize; - if (rows==0) - rows=1; - else if (rows>0xFFFFFFFF) - rows=0xFFFFFFFF; - s=(uint32)rows; - } - return (s); + if ((int32) s < 1) { + /* + * If RowsPerStrip is unspecified, try to break the + * image up into strips that are approximately + * STRIP_SIZE_DEFAULT bytes long. + */ + uint64 scanlinesize; + uint64 rows; + scanlinesize=TIFFScanlineSize64(tif); + if (scanlinesize==0) + scanlinesize=1; + rows=(uint64)STRIP_SIZE_DEFAULT/scanlinesize; + if (rows==0) + rows=1; + else if (rows>0xFFFFFFFF) + rows=0xFFFFFFFF; + s=(uint32)rows; + } + return (s); } /* @@ -273,67 +273,73 @@ _TIFFDefaultStripSize(TIFF* tif, uint32 s) uint64 TIFFScanlineSize64(TIFF* tif) { - static const char module[] = "TIFFScanlineSize64"; - TIFFDirectory *td = &tif->tif_dir; - uint64 scanline_size; - if (td->td_planarconfig==PLANARCONFIG_CONTIG) - { - if ((td->td_photometric==PHOTOMETRIC_YCBCR)&& - (td->td_samplesperpixel==3)&& - (!isUpSampled(tif))) - { - uint16 ycbcrsubsampling[2]; - uint16 samplingblock_samples; - uint32 samplingblocks_hor; - uint64 samplingrow_samples; - uint64 samplingrow_size; - if(td->td_samplesperpixel!=3) - { + static const char module[] = "TIFFScanlineSize64"; + TIFFDirectory *td = &tif->tif_dir; + uint64 scanline_size; + if (td->td_planarconfig==PLANARCONFIG_CONTIG) + { + if ((td->td_photometric==PHOTOMETRIC_YCBCR)&& + (td->td_samplesperpixel==3)&& + (!isUpSampled(tif))) + { + uint16 ycbcrsubsampling[2]; + uint16 samplingblock_samples; + uint32 samplingblocks_hor; + uint64 samplingrow_samples; + uint64 samplingrow_size; + if(td->td_samplesperpixel!=3) + { TIFFErrorExt(tif->tif_clientdata,module, "Invalid td_samplesperpixel value"); return 0; - } - TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING, + } + TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING, ycbcrsubsampling+0, ycbcrsubsampling+1); - if (((ycbcrsubsampling[0]!=1)&&(ycbcrsubsampling[0]!=2)&&(ycbcrsubsampling[0]!=4)) || - ((ycbcrsubsampling[1]!=1)&&(ycbcrsubsampling[1]!=2)&&(ycbcrsubsampling[1]!=4))) - { + if (((ycbcrsubsampling[0]!=1)&&(ycbcrsubsampling[0]!=2)&&(ycbcrsubsampling[0]!=4)) || + ((ycbcrsubsampling[1]!=1)&&(ycbcrsubsampling[1]!=2)&&(ycbcrsubsampling[1]!=4))) + { TIFFErrorExt(tif->tif_clientdata,module, "Invalid YCbCr subsampling"); return 0; - } - samplingblock_samples = ycbcrsubsampling[0]*ycbcrsubsampling[1]+2; - samplingblocks_hor = TIFFhowmany_32(td->td_imagewidth,ycbcrsubsampling[0]); - samplingrow_samples = _TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module); - samplingrow_size = TIFFhowmany_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module),8); - scanline_size = (samplingrow_size/ycbcrsubsampling[1]); - } - else + } + samplingblock_samples = ycbcrsubsampling[0]*ycbcrsubsampling[1]+2; + samplingblocks_hor = TIFFhowmany_32(td->td_imagewidth,ycbcrsubsampling[0]); + samplingrow_samples = _TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module); + samplingrow_size = TIFFhowmany_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module),8); + scanline_size = (samplingrow_size/ycbcrsubsampling[1]); + } + else + { + uint64 scanline_samples; + scanline_samples=_TIFFMultiply64(tif,td->td_imagewidth,td->td_samplesperpixel,module); + scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,scanline_samples,td->td_bitspersample,module),8); + } + } + else { - uint64 scanline_samples; - scanline_samples=_TIFFMultiply64(tif,td->td_imagewidth,td->td_samplesperpixel,module); - scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,scanline_samples,td->td_bitspersample,module),8); + scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,td->td_imagewidth,td->td_bitspersample,module),8); } - } - else - scanline_size=TIFFhowmany_64(_TIFFMultiply64(tif,td->td_imagewidth,td->td_bitspersample,module),8); - return(scanline_size); + if (scanline_size == 0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Computed scanline size is zero"); + return 0; + } + return(scanline_size); } tmsize_t TIFFScanlineSize(TIFF* tif) { - static const char module[] = "TIFFScanlineSize"; - uint64 m; - tmsize_t n; - m=TIFFScanlineSize64(tif); - n=(tmsize_t)m; - if ((uint64)n!=m) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow"); - n=0; - } - return(n); + static const char module[] = "TIFFScanlineSize"; + uint64 m; + tmsize_t n; + m=TIFFScanlineSize64(tif); + n=(tmsize_t)m; + if ((uint64)n!=m) { + TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow"); + n=0; + } + return(n); } /* @@ -345,32 +351,32 @@ TIFFScanlineSize(TIFF* tif) uint64 TIFFRasterScanlineSize64(TIFF* tif) { - static const char module[] = "TIFFRasterScanlineSize64"; - TIFFDirectory *td = &tif->tif_dir; - uint64 scanline; + static const char module[] = "TIFFRasterScanlineSize64"; + TIFFDirectory *td = &tif->tif_dir; + uint64 scanline; - scanline = _TIFFMultiply64(tif, td->td_bitspersample, td->td_imagewidth, module); - if (td->td_planarconfig == PLANARCONFIG_CONTIG) { - scanline = _TIFFMultiply64(tif, scanline, td->td_samplesperpixel, module); - return (TIFFhowmany8_64(scanline)); - } else - return (_TIFFMultiply64(tif, TIFFhowmany8_64(scanline), - td->td_samplesperpixel, module)); + scanline = _TIFFMultiply64(tif, td->td_bitspersample, td->td_imagewidth, module); + if (td->td_planarconfig == PLANARCONFIG_CONTIG) { + scanline = _TIFFMultiply64(tif, scanline, td->td_samplesperpixel, module); + return (TIFFhowmany8_64(scanline)); + } else + return (_TIFFMultiply64(tif, TIFFhowmany8_64(scanline), + td->td_samplesperpixel, module)); } tmsize_t TIFFRasterScanlineSize(TIFF* tif) { - static const char module[] = "TIFFRasterScanlineSize"; - uint64 m; - tmsize_t n; - m=TIFFRasterScanlineSize64(tif); - n=(tmsize_t)m; - if ((uint64)n!=m) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow"); - n=0; - } - return(n); + static const char module[] = "TIFFRasterScanlineSize"; + uint64 m; + tmsize_t n; + m=TIFFRasterScanlineSize64(tif); + n=(tmsize_t)m; + if ((uint64)n!=m) + { + TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow"); + n=0; + } + return(n); } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_swab.c b/3rdparty/libtiff/tif_swab.c index b1f7c3a7ef..4b2e5f16d7 100644 --- a/3rdparty/libtiff/tif_swab.c +++ b/3rdparty/libtiff/tif_swab.c @@ -1,26 +1,26 @@ -/* $Id: tif_swab.c,v 1.13 2010-03-10 18:56:49 bfriesen Exp $ */ +/* $Id: tif_swab.c,v 1.15 2017-06-08 16:39:50 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -31,170 +31,170 @@ */ #include "tiffiop.h" -#ifndef TIFFSwabShort +#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabShort) void TIFFSwabShort(uint16* wp) { - register unsigned char* cp = (unsigned char*) wp; - unsigned char t; - assert(sizeof(uint16)==2); - t = cp[1]; cp[1] = cp[0]; cp[0] = t; + register unsigned char* cp = (unsigned char*) wp; + unsigned char t; + assert(sizeof(uint16)==2); + t = cp[1]; cp[1] = cp[0]; cp[0] = t; } #endif -#ifndef TIFFSwabLong +#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabLong) void TIFFSwabLong(uint32* lp) { - register unsigned char* cp = (unsigned char*) lp; - unsigned char t; - assert(sizeof(uint32)==4); - t = cp[3]; cp[3] = cp[0]; cp[0] = t; - t = cp[2]; cp[2] = cp[1]; cp[1] = t; + register unsigned char* cp = (unsigned char*) lp; + unsigned char t; + assert(sizeof(uint32)==4); + t = cp[3]; cp[3] = cp[0]; cp[0] = t; + t = cp[2]; cp[2] = cp[1]; cp[1] = t; } #endif -#ifndef TIFFSwabLong8 +#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabLong8) void TIFFSwabLong8(uint64* lp) { - register unsigned char* cp = (unsigned char*) lp; - unsigned char t; - assert(sizeof(uint64)==8); - t = cp[7]; cp[7] = cp[0]; cp[0] = t; - t = cp[6]; cp[6] = cp[1]; cp[1] = t; - t = cp[5]; cp[5] = cp[2]; cp[2] = t; - t = cp[4]; cp[4] = cp[3]; cp[3] = t; + register unsigned char* cp = (unsigned char*) lp; + unsigned char t; + assert(sizeof(uint64)==8); + t = cp[7]; cp[7] = cp[0]; cp[0] = t; + t = cp[6]; cp[6] = cp[1]; cp[1] = t; + t = cp[5]; cp[5] = cp[2]; cp[2] = t; + t = cp[4]; cp[4] = cp[3]; cp[3] = t; } #endif -#ifndef TIFFSwabArrayOfShort +#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfShort) void TIFFSwabArrayOfShort(register uint16* wp, tmsize_t n) { - register unsigned char* cp; - register unsigned char t; - assert(sizeof(uint16)==2); - /* XXX unroll loop some */ - while (n-- > 0) { - cp = (unsigned char*) wp; - t = cp[1]; cp[1] = cp[0]; cp[0] = t; - wp++; - } + register unsigned char* cp; + register unsigned char t; + assert(sizeof(uint16)==2); + /* XXX unroll loop some */ + while (n-- > 0) { + cp = (unsigned char*) wp; + t = cp[1]; cp[1] = cp[0]; cp[0] = t; + wp++; + } } #endif -#ifndef TIFFSwabArrayOfTriples +#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfTriples) void TIFFSwabArrayOfTriples(register uint8* tp, tmsize_t n) { - unsigned char* cp; - unsigned char t; + unsigned char* cp; + unsigned char t; - /* XXX unroll loop some */ - while (n-- > 0) { - cp = (unsigned char*) tp; - t = cp[2]; cp[2] = cp[0]; cp[0] = t; - tp += 3; - } + /* XXX unroll loop some */ + while (n-- > 0) { + cp = (unsigned char*) tp; + t = cp[2]; cp[2] = cp[0]; cp[0] = t; + tp += 3; + } } #endif -#ifndef TIFFSwabArrayOfLong +#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfLong) void TIFFSwabArrayOfLong(register uint32* lp, tmsize_t n) { - register unsigned char *cp; - register unsigned char t; - assert(sizeof(uint32)==4); - /* XXX unroll loop some */ - while (n-- > 0) { - cp = (unsigned char *)lp; - t = cp[3]; cp[3] = cp[0]; cp[0] = t; - t = cp[2]; cp[2] = cp[1]; cp[1] = t; - lp++; - } + register unsigned char *cp; + register unsigned char t; + assert(sizeof(uint32)==4); + /* XXX unroll loop some */ + while (n-- > 0) { + cp = (unsigned char *)lp; + t = cp[3]; cp[3] = cp[0]; cp[0] = t; + t = cp[2]; cp[2] = cp[1]; cp[1] = t; + lp++; + } } #endif -#ifndef TIFFSwabArrayOfLong8 +#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfLong8) void TIFFSwabArrayOfLong8(register uint64* lp, tmsize_t n) { - register unsigned char *cp; - register unsigned char t; - assert(sizeof(uint64)==8); - /* XXX unroll loop some */ - while (n-- > 0) { - cp = (unsigned char *)lp; - t = cp[7]; cp[7] = cp[0]; cp[0] = t; - t = cp[6]; cp[6] = cp[1]; cp[1] = t; - t = cp[5]; cp[5] = cp[2]; cp[2] = t; - t = cp[4]; cp[4] = cp[3]; cp[3] = t; - lp++; - } + register unsigned char *cp; + register unsigned char t; + assert(sizeof(uint64)==8); + /* XXX unroll loop some */ + while (n-- > 0) { + cp = (unsigned char *)lp; + t = cp[7]; cp[7] = cp[0]; cp[0] = t; + t = cp[6]; cp[6] = cp[1]; cp[1] = t; + t = cp[5]; cp[5] = cp[2]; cp[2] = t; + t = cp[4]; cp[4] = cp[3]; cp[3] = t; + lp++; + } } #endif -#ifndef TIFFSwabFloat +#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabFloat) void TIFFSwabFloat(float* fp) { - register unsigned char* cp = (unsigned char*) fp; - unsigned char t; - assert(sizeof(float)==4); - t = cp[3]; cp[3] = cp[0]; cp[0] = t; - t = cp[2]; cp[2] = cp[1]; cp[1] = t; + register unsigned char* cp = (unsigned char*) fp; + unsigned char t; + assert(sizeof(float)==4); + t = cp[3]; cp[3] = cp[0]; cp[0] = t; + t = cp[2]; cp[2] = cp[1]; cp[1] = t; } #endif -#ifndef TIFFSwabArrayOfFloat +#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfFloat) void TIFFSwabArrayOfFloat(register float* fp, tmsize_t n) { - register unsigned char *cp; - register unsigned char t; - assert(sizeof(float)==4); - /* XXX unroll loop some */ - while (n-- > 0) { - cp = (unsigned char *)fp; - t = cp[3]; cp[3] = cp[0]; cp[0] = t; - t = cp[2]; cp[2] = cp[1]; cp[1] = t; - fp++; - } + register unsigned char *cp; + register unsigned char t; + assert(sizeof(float)==4); + /* XXX unroll loop some */ + while (n-- > 0) { + cp = (unsigned char *)fp; + t = cp[3]; cp[3] = cp[0]; cp[0] = t; + t = cp[2]; cp[2] = cp[1]; cp[1] = t; + fp++; + } } #endif -#ifndef TIFFSwabDouble +#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabDouble) void TIFFSwabDouble(double *dp) { - register unsigned char* cp = (unsigned char*) dp; - unsigned char t; - assert(sizeof(double)==8); - t = cp[7]; cp[7] = cp[0]; cp[0] = t; - t = cp[6]; cp[6] = cp[1]; cp[1] = t; - t = cp[5]; cp[5] = cp[2]; cp[2] = t; - t = cp[4]; cp[4] = cp[3]; cp[3] = t; + register unsigned char* cp = (unsigned char*) dp; + unsigned char t; + assert(sizeof(double)==8); + t = cp[7]; cp[7] = cp[0]; cp[0] = t; + t = cp[6]; cp[6] = cp[1]; cp[1] = t; + t = cp[5]; cp[5] = cp[2]; cp[2] = t; + t = cp[4]; cp[4] = cp[3]; cp[3] = t; } #endif -#ifndef TIFFSwabArrayOfDouble +#if defined(DISABLE_CHECK_TIFFSWABMACROS) || !defined(TIFFSwabArrayOfDouble) void TIFFSwabArrayOfDouble(double* dp, tmsize_t n) { - register unsigned char *cp; - register unsigned char t; - assert(sizeof(double)==8); - /* XXX unroll loop some */ - while (n-- > 0) { - cp = (unsigned char *)dp; - t = cp[7]; cp[7] = cp[0]; cp[0] = t; - t = cp[6]; cp[6] = cp[1]; cp[1] = t; - t = cp[5]; cp[5] = cp[2]; cp[2] = t; - t = cp[4]; cp[4] = cp[3]; cp[3] = t; - dp++; - } + register unsigned char *cp; + register unsigned char t; + assert(sizeof(double)==8); + /* XXX unroll loop some */ + while (n-- > 0) { + cp = (unsigned char *)dp; + t = cp[7]; cp[7] = cp[0]; cp[0] = t; + t = cp[6]; cp[6] = cp[1]; cp[1] = t; + t = cp[5]; cp[5] = cp[2]; cp[2] = t; + t = cp[4]; cp[4] = cp[3]; cp[3] = t; + dp++; + } } #endif @@ -242,62 +242,64 @@ static const unsigned char TIFFBitRevTable[256] = { 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff }; static const unsigned char TIFFNoBitRevTable[256] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, }; const unsigned char* TIFFGetBitRevTable(int reversed) { - return (reversed ? TIFFBitRevTable : TIFFNoBitRevTable); + return (reversed ? TIFFBitRevTable : TIFFNoBitRevTable); } void -TIFFReverseBits(uint8* cp, tmsize_t n) +TIFFReverseBits(uint8* cp, tmsize_t n) { - for (; n > 8; n -= 8) { - cp[0] = TIFFBitRevTable[cp[0]]; - cp[1] = TIFFBitRevTable[cp[1]]; - cp[2] = TIFFBitRevTable[cp[2]]; - cp[3] = TIFFBitRevTable[cp[3]]; - cp[4] = TIFFBitRevTable[cp[4]]; - cp[5] = TIFFBitRevTable[cp[5]]; - cp[6] = TIFFBitRevTable[cp[6]]; - cp[7] = TIFFBitRevTable[cp[7]]; - cp += 8; - } - while (n-- > 0) - *cp = TIFFBitRevTable[*cp], cp++; + for (; n > 8; n -= 8) { + cp[0] = TIFFBitRevTable[cp[0]]; + cp[1] = TIFFBitRevTable[cp[1]]; + cp[2] = TIFFBitRevTable[cp[2]]; + cp[3] = TIFFBitRevTable[cp[3]]; + cp[4] = TIFFBitRevTable[cp[4]]; + cp[5] = TIFFBitRevTable[cp[5]]; + cp[6] = TIFFBitRevTable[cp[6]]; + cp[7] = TIFFBitRevTable[cp[7]]; + cp += 8; + } + while (n-- > 0) { + *cp = TIFFBitRevTable[*cp]; + cp++; + } } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_thunder.c b/3rdparty/libtiff/tif_thunder.c index a9e0100f8e..183199de76 100644 --- a/3rdparty/libtiff/tif_thunder.c +++ b/3rdparty/libtiff/tif_thunder.c @@ -1,26 +1,26 @@ -/* $Id: tif_thunder.c,v 1.12 2011-04-02 20:54:09 bfriesen Exp $ */ +/* $Id: tif_thunder.c,v 1.13 2016-09-04 21:32:56 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -57,20 +57,20 @@ static const int twobitdeltas[4] = { 0, 1, 0, -1 }; static const int threebitdeltas[8] = { 0, 1, 2, 3, 0, -3, -2, -1 }; #define SETPIXEL(op, v) { \ - lastpixel = (v) & 0xf; \ + lastpixel = (v) & 0xf; \ if ( npixels < maxpixels ) \ { \ - if (npixels++ & 1) \ - *op++ |= lastpixel; \ - else \ - op[0] = (uint8) (lastpixel << 4); \ + if (npixels++ & 1) \ + *op++ |= lastpixel; \ + else \ + op[0] = (uint8) (lastpixel << 4); \ } \ } static int ThunderSetupDecode(TIFF* tif) { - static const char module[] = "ThunderSetupDecode"; + static const char module[] = "ThunderSetupDecode"; if( tif->tif_dir.td_bitspersample != 4 ) { @@ -79,87 +79,88 @@ ThunderSetupDecode(TIFF* tif) (int) tif->tif_dir.td_bitspersample ); return 0; } + - - return (1); + return (1); } static int ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels) { - static const char module[] = "ThunderDecode"; - register unsigned char *bp; - register tmsize_t cc; - unsigned int lastpixel; - tmsize_t npixels; + static const char module[] = "ThunderDecode"; + register unsigned char *bp; + register tmsize_t cc; + unsigned int lastpixel; + tmsize_t npixels; - bp = (unsigned char *)tif->tif_rawcp; - cc = tif->tif_rawcc; - lastpixel = 0; - npixels = 0; - while (cc > 0 && npixels < maxpixels) { - int n, delta; + bp = (unsigned char *)tif->tif_rawcp; + cc = tif->tif_rawcc; + lastpixel = 0; + npixels = 0; + while (cc > 0 && npixels < maxpixels) { + int n, delta; - n = *bp++, cc--; - switch (n & THUNDER_CODE) { - case THUNDER_RUN: /* pixel run */ - /* - * Replicate the last pixel n times, - * where n is the lower-order 6 bits. - */ - if (npixels & 1) { - op[0] |= lastpixel; - lastpixel = *op++; npixels++; n--; - } else - lastpixel |= lastpixel << 4; - npixels += n; - if (npixels < maxpixels) { - for (; n > 0; n -= 2) - *op++ = (uint8) lastpixel; - } - if (n == -1) - *--op &= 0xf0; - lastpixel &= 0xf; - break; - case THUNDER_2BITDELTAS: /* 2-bit deltas */ - if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP) - SETPIXEL(op, lastpixel + twobitdeltas[delta]); - if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP) - SETPIXEL(op, lastpixel + twobitdeltas[delta]); - if ((delta = (n & 3)) != DELTA2_SKIP) - SETPIXEL(op, lastpixel + twobitdeltas[delta]); - break; - case THUNDER_3BITDELTAS: /* 3-bit deltas */ - if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP) - SETPIXEL(op, lastpixel + threebitdeltas[delta]); - if ((delta = (n & 7)) != DELTA3_SKIP) - SETPIXEL(op, lastpixel + threebitdeltas[delta]); - break; - case THUNDER_RAW: /* raw data */ - SETPIXEL(op, n); - break; - } - } - tif->tif_rawcp = (uint8*) bp; - tif->tif_rawcc = cc; - if (npixels != maxpixels) { + n = *bp++; + cc--; + switch (n & THUNDER_CODE) { + case THUNDER_RUN: /* pixel run */ + /* + * Replicate the last pixel n times, + * where n is the lower-order 6 bits. + */ + if (npixels & 1) { + op[0] |= lastpixel; + lastpixel = *op++; npixels++; n--; + } else + lastpixel |= lastpixel << 4; + npixels += n; + if (npixels < maxpixels) { + for (; n > 0; n -= 2) + *op++ = (uint8) lastpixel; + } + if (n == -1) + *--op &= 0xf0; + lastpixel &= 0xf; + break; + case THUNDER_2BITDELTAS: /* 2-bit deltas */ + if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP) + SETPIXEL(op, lastpixel + twobitdeltas[delta]); + if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP) + SETPIXEL(op, lastpixel + twobitdeltas[delta]); + if ((delta = (n & 3)) != DELTA2_SKIP) + SETPIXEL(op, lastpixel + twobitdeltas[delta]); + break; + case THUNDER_3BITDELTAS: /* 3-bit deltas */ + if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP) + SETPIXEL(op, lastpixel + threebitdeltas[delta]); + if ((delta = (n & 7)) != DELTA3_SKIP) + SETPIXEL(op, lastpixel + threebitdeltas[delta]); + break; + case THUNDER_RAW: /* raw data */ + SETPIXEL(op, n); + break; + } + } + tif->tif_rawcp = (uint8*) bp; + tif->tif_rawcc = cc; + if (npixels != maxpixels) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) - TIFFErrorExt(tif->tif_clientdata, module, - "%s data at scanline %lu (%I64u != %I64u)", - npixels < maxpixels ? "Not enough" : "Too much", - (unsigned long) tif->tif_row, - (unsigned __int64) npixels, - (unsigned __int64) maxpixels); + TIFFErrorExt(tif->tif_clientdata, module, + "%s data at scanline %lu (%I64u != %I64u)", + npixels < maxpixels ? "Not enough" : "Too much", + (unsigned long) tif->tif_row, + (unsigned __int64) npixels, + (unsigned __int64) maxpixels); #else - TIFFErrorExt(tif->tif_clientdata, module, - "%s data at scanline %lu (%llu != %llu)", - npixels < maxpixels ? "Not enough" : "Too much", - (unsigned long) tif->tif_row, - (unsigned long long) npixels, - (unsigned long long) maxpixels); + TIFFErrorExt(tif->tif_clientdata, module, + "%s data at scanline %lu (%llu != %llu)", + npixels < maxpixels ? "Not enough" : "Too much", + (unsigned long) tif->tif_row, + (unsigned long long) npixels, + (unsigned long long) maxpixels); #endif - return (0); - } + return (0); + } return (1); } @@ -167,33 +168,33 @@ ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels) static int ThunderDecodeRow(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) { - static const char module[] = "ThunderDecodeRow"; - uint8* row = buf; - - (void) s; - if (occ % tif->tif_scanlinesize) - { - TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); - return (0); - } - while (occ > 0) { - if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth)) - return (0); - occ -= tif->tif_scanlinesize; - row += tif->tif_scanlinesize; - } - return (1); + static const char module[] = "ThunderDecodeRow"; + uint8* row = buf; + + (void) s; + if (occ % tif->tif_scanlinesize) + { + TIFFErrorExt(tif->tif_clientdata, module, "Fractional scanlines cannot be read"); + return (0); + } + while (occ > 0) { + if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth)) + return (0); + occ -= tif->tif_scanlinesize; + row += tif->tif_scanlinesize; + } + return (1); } int TIFFInitThunderScan(TIFF* tif, int scheme) { - (void) scheme; + (void) scheme; tif->tif_setupdecode = ThunderSetupDecode; - tif->tif_decoderow = ThunderDecodeRow; - tif->tif_decodestrip = ThunderDecodeRow; - return (1); + tif->tif_decoderow = ThunderDecodeRow; + tif->tif_decodestrip = ThunderDecodeRow; + return (1); } #endif /* THUNDER_SUPPORT */ diff --git a/3rdparty/libtiff/tif_tile.c b/3rdparty/libtiff/tif_tile.c index 11d3c5aa80..388e168ac6 100644 --- a/3rdparty/libtiff/tif_tile.c +++ b/3rdparty/libtiff/tif_tile.c @@ -1,26 +1,26 @@ -/* $Id: tif_tile.c,v 1.23 2012-06-06 05:33:55 fwarmerdam Exp $ */ +/* $Id: tif_tile.c,v 1.24 2015-06-07 22:35:40 bfriesen Exp $ */ /* * Copyright (c) 1991-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -37,34 +37,34 @@ uint32 TIFFComputeTile(TIFF* tif, uint32 x, uint32 y, uint32 z, uint16 s) { - TIFFDirectory *td = &tif->tif_dir; - uint32 dx = td->td_tilewidth; - uint32 dy = td->td_tilelength; - uint32 dz = td->td_tiledepth; - uint32 tile = 1; + TIFFDirectory *td = &tif->tif_dir; + uint32 dx = td->td_tilewidth; + uint32 dy = td->td_tilelength; + uint32 dz = td->td_tiledepth; + uint32 tile = 1; - if (td->td_imagedepth == 1) - z = 0; - if (dx == (uint32) -1) - dx = td->td_imagewidth; - if (dy == (uint32) -1) - dy = td->td_imagelength; - if (dz == (uint32) -1) - dz = td->td_imagedepth; - if (dx != 0 && dy != 0 && dz != 0) { - uint32 xpt = TIFFhowmany_32(td->td_imagewidth, dx); - uint32 ypt = TIFFhowmany_32(td->td_imagelength, dy); - uint32 zpt = TIFFhowmany_32(td->td_imagedepth, dz); + if (td->td_imagedepth == 1) + z = 0; + if (dx == (uint32) -1) + dx = td->td_imagewidth; + if (dy == (uint32) -1) + dy = td->td_imagelength; + if (dz == (uint32) -1) + dz = td->td_imagedepth; + if (dx != 0 && dy != 0 && dz != 0) { + uint32 xpt = TIFFhowmany_32(td->td_imagewidth, dx); + uint32 ypt = TIFFhowmany_32(td->td_imagelength, dy); + uint32 zpt = TIFFhowmany_32(td->td_imagedepth, dz); - if (td->td_planarconfig == PLANARCONFIG_SEPARATE) - tile = (xpt*ypt*zpt)*s + - (xpt*ypt)*(z/dz) + - xpt*(y/dy) + - x/dx; - else - tile = (xpt*ypt)*(z/dz) + xpt*(y/dy) + x/dx; - } - return (tile); + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + tile = (xpt*ypt*zpt)*s + + (xpt*ypt)*(z/dz) + + xpt*(y/dy) + + x/dx; + else + tile = (xpt*ypt)*(z/dz) + xpt*(y/dy) + x/dx; + } + return (tile); } /* @@ -74,38 +74,38 @@ TIFFComputeTile(TIFF* tif, uint32 x, uint32 y, uint32 z, uint16 s) int TIFFCheckTile(TIFF* tif, uint32 x, uint32 y, uint32 z, uint16 s) { - TIFFDirectory *td = &tif->tif_dir; + TIFFDirectory *td = &tif->tif_dir; - if (x >= td->td_imagewidth) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "%lu: Col out of range, max %lu", - (unsigned long) x, - (unsigned long) (td->td_imagewidth - 1)); - return (0); - } - if (y >= td->td_imagelength) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "%lu: Row out of range, max %lu", - (unsigned long) y, - (unsigned long) (td->td_imagelength - 1)); - return (0); - } - if (z >= td->td_imagedepth) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "%lu: Depth out of range, max %lu", - (unsigned long) z, - (unsigned long) (td->td_imagedepth - 1)); - return (0); - } - if (td->td_planarconfig == PLANARCONFIG_SEPARATE && - s >= td->td_samplesperpixel) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "%lu: Sample out of range, max %lu", - (unsigned long) s, - (unsigned long) (td->td_samplesperpixel - 1)); - return (0); - } - return (1); + if (x >= td->td_imagewidth) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Col out of range, max %lu", + (unsigned long) x, + (unsigned long) (td->td_imagewidth - 1)); + return (0); + } + if (y >= td->td_imagelength) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Row out of range, max %lu", + (unsigned long) y, + (unsigned long) (td->td_imagelength - 1)); + return (0); + } + if (z >= td->td_imagedepth) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Depth out of range, max %lu", + (unsigned long) z, + (unsigned long) (td->td_imagedepth - 1)); + return (0); + } + if (td->td_planarconfig == PLANARCONFIG_SEPARATE && + s >= td->td_samplesperpixel) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "%lu: Sample out of range, max %lu", + (unsigned long) s, + (unsigned long) (td->td_samplesperpixel - 1)); + return (0); + } + return (1); } /* @@ -114,27 +114,27 @@ TIFFCheckTile(TIFF* tif, uint32 x, uint32 y, uint32 z, uint16 s) uint32 TIFFNumberOfTiles(TIFF* tif) { - TIFFDirectory *td = &tif->tif_dir; - uint32 dx = td->td_tilewidth; - uint32 dy = td->td_tilelength; - uint32 dz = td->td_tiledepth; - uint32 ntiles; + TIFFDirectory *td = &tif->tif_dir; + uint32 dx = td->td_tilewidth; + uint32 dy = td->td_tilelength; + uint32 dz = td->td_tiledepth; + uint32 ntiles; - if (dx == (uint32) -1) - dx = td->td_imagewidth; - if (dy == (uint32) -1) - dy = td->td_imagelength; - if (dz == (uint32) -1) - dz = td->td_imagedepth; - ntiles = (dx == 0 || dy == 0 || dz == 0) ? 0 : - _TIFFMultiply32(tif, _TIFFMultiply32(tif, TIFFhowmany_32(td->td_imagewidth, dx), - TIFFhowmany_32(td->td_imagelength, dy), - "TIFFNumberOfTiles"), - TIFFhowmany_32(td->td_imagedepth, dz), "TIFFNumberOfTiles"); - if (td->td_planarconfig == PLANARCONFIG_SEPARATE) - ntiles = _TIFFMultiply32(tif, ntiles, td->td_samplesperpixel, - "TIFFNumberOfTiles"); - return (ntiles); + if (dx == (uint32) -1) + dx = td->td_imagewidth; + if (dy == (uint32) -1) + dy = td->td_imagelength; + if (dz == (uint32) -1) + dz = td->td_imagedepth; + ntiles = (dx == 0 || dy == 0 || dz == 0) ? 0 : + _TIFFMultiply32(tif, _TIFFMultiply32(tif, TIFFhowmany_32(td->td_imagewidth, dx), + TIFFhowmany_32(td->td_imagelength, dy), + "TIFFNumberOfTiles"), + TIFFhowmany_32(td->td_imagedepth, dz), "TIFFNumberOfTiles"); + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + ntiles = _TIFFMultiply32(tif, ntiles, td->td_samplesperpixel, + "TIFFNumberOfTiles"); + return (ntiles); } /* @@ -143,32 +143,55 @@ TIFFNumberOfTiles(TIFF* tif) uint64 TIFFTileRowSize64(TIFF* tif) { - TIFFDirectory *td = &tif->tif_dir; - uint64 rowsize; + static const char module[] = "TIFFTileRowSize64"; + TIFFDirectory *td = &tif->tif_dir; + uint64 rowsize; + uint64 tilerowsize; - if (td->td_tilelength == 0 || td->td_tilewidth == 0) - return (0); - rowsize = _TIFFMultiply64(tif, td->td_bitspersample, td->td_tilewidth, - "TIFFTileRowSize"); - if (td->td_planarconfig == PLANARCONFIG_CONTIG) - rowsize = _TIFFMultiply64(tif, rowsize, td->td_samplesperpixel, - "TIFFTileRowSize"); - return (TIFFhowmany8_64(rowsize)); + if (td->td_tilelength == 0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Tile length is zero"); + return 0; + } + if (td->td_tilewidth == 0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Tile width is zero"); + return (0); + } + rowsize = _TIFFMultiply64(tif, td->td_bitspersample, td->td_tilewidth, + "TIFFTileRowSize"); + if (td->td_planarconfig == PLANARCONFIG_CONTIG) + { + if (td->td_samplesperpixel == 0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Samples per pixel is zero"); + return 0; + } + rowsize = _TIFFMultiply64(tif, rowsize, td->td_samplesperpixel, + "TIFFTileRowSize"); + } + tilerowsize=TIFFhowmany8_64(rowsize); + if (tilerowsize == 0) + { + TIFFErrorExt(tif->tif_clientdata,module,"Computed tile row size is zero"); + return 0; + } + return (tilerowsize); } tmsize_t TIFFTileRowSize(TIFF* tif) { - static const char module[] = "TIFFTileRowSize"; - uint64 m; - tmsize_t n; - m=TIFFTileRowSize64(tif); - n=(tmsize_t)m; - if ((uint64)n!=m) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); - n=0; - } - return(n); + static const char module[] = "TIFFTileRowSize"; + uint64 m; + tmsize_t n; + m=TIFFTileRowSize64(tif); + n=(tmsize_t)m; + if ((uint64)n!=m) + { + TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); + n=0; + } + return(n); } /* @@ -177,65 +200,65 @@ TIFFTileRowSize(TIFF* tif) uint64 TIFFVTileSize64(TIFF* tif, uint32 nrows) { - static const char module[] = "TIFFVTileSize64"; - TIFFDirectory *td = &tif->tif_dir; - if (td->td_tilelength == 0 || td->td_tilewidth == 0 || - td->td_tiledepth == 0) - return (0); - if ((td->td_planarconfig==PLANARCONFIG_CONTIG)&& - (td->td_photometric==PHOTOMETRIC_YCBCR)&& - (td->td_samplesperpixel==3)&& - (!isUpSampled(tif))) - { - /* - * Packed YCbCr data contain one Cb+Cr for every - * HorizontalSampling*VerticalSampling Y values. - * Must also roundup width and height when calculating - * since images that are not a multiple of the - * horizontal/vertical subsampling area include - * YCbCr data for the extended image. - */ - uint16 ycbcrsubsampling[2]; - uint16 samplingblock_samples; - uint32 samplingblocks_hor; - uint32 samplingblocks_ver; - uint64 samplingrow_samples; - uint64 samplingrow_size; - TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING,ycbcrsubsampling+0, - ycbcrsubsampling+1); - if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 && ycbcrsubsampling[0] != 4) - ||(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 && ycbcrsubsampling[1] != 4)) - { - TIFFErrorExt(tif->tif_clientdata,module, - "Invalid YCbCr subsampling (%dx%d)", - ycbcrsubsampling[0], - ycbcrsubsampling[1] ); - return 0; - } - samplingblock_samples=ycbcrsubsampling[0]*ycbcrsubsampling[1]+2; - samplingblocks_hor=TIFFhowmany_32(td->td_tilewidth,ycbcrsubsampling[0]); - samplingblocks_ver=TIFFhowmany_32(nrows,ycbcrsubsampling[1]); - samplingrow_samples=_TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module); - samplingrow_size=TIFFhowmany8_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module)); - return(_TIFFMultiply64(tif,samplingrow_size,samplingblocks_ver,module)); - } - else - return(_TIFFMultiply64(tif,nrows,TIFFTileRowSize64(tif),module)); + static const char module[] = "TIFFVTileSize64"; + TIFFDirectory *td = &tif->tif_dir; + if (td->td_tilelength == 0 || td->td_tilewidth == 0 || + td->td_tiledepth == 0) + return (0); + if ((td->td_planarconfig==PLANARCONFIG_CONTIG)&& + (td->td_photometric==PHOTOMETRIC_YCBCR)&& + (td->td_samplesperpixel==3)&& + (!isUpSampled(tif))) + { + /* + * Packed YCbCr data contain one Cb+Cr for every + * HorizontalSampling*VerticalSampling Y values. + * Must also roundup width and height when calculating + * since images that are not a multiple of the + * horizontal/vertical subsampling area include + * YCbCr data for the extended image. + */ + uint16 ycbcrsubsampling[2]; + uint16 samplingblock_samples; + uint32 samplingblocks_hor; + uint32 samplingblocks_ver; + uint64 samplingrow_samples; + uint64 samplingrow_size; + TIFFGetFieldDefaulted(tif,TIFFTAG_YCBCRSUBSAMPLING,ycbcrsubsampling+0, + ycbcrsubsampling+1); + if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 && ycbcrsubsampling[0] != 4) + ||(ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 && ycbcrsubsampling[1] != 4)) + { + TIFFErrorExt(tif->tif_clientdata,module, + "Invalid YCbCr subsampling (%dx%d)", + ycbcrsubsampling[0], + ycbcrsubsampling[1] ); + return 0; + } + samplingblock_samples=ycbcrsubsampling[0]*ycbcrsubsampling[1]+2; + samplingblocks_hor=TIFFhowmany_32(td->td_tilewidth,ycbcrsubsampling[0]); + samplingblocks_ver=TIFFhowmany_32(nrows,ycbcrsubsampling[1]); + samplingrow_samples=_TIFFMultiply64(tif,samplingblocks_hor,samplingblock_samples,module); + samplingrow_size=TIFFhowmany8_64(_TIFFMultiply64(tif,samplingrow_samples,td->td_bitspersample,module)); + return(_TIFFMultiply64(tif,samplingrow_size,samplingblocks_ver,module)); + } + else + return(_TIFFMultiply64(tif,nrows,TIFFTileRowSize64(tif),module)); } tmsize_t TIFFVTileSize(TIFF* tif, uint32 nrows) { - static const char module[] = "TIFFVTileSize"; - uint64 m; - tmsize_t n; - m=TIFFVTileSize64(tif,nrows); - n=(tmsize_t)m; - if ((uint64)n!=m) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); - n=0; - } - return(n); + static const char module[] = "TIFFVTileSize"; + uint64 m; + tmsize_t n; + m=TIFFVTileSize64(tif,nrows); + n=(tmsize_t)m; + if ((uint64)n!=m) + { + TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); + n=0; + } + return(n); } /* @@ -244,22 +267,22 @@ TIFFVTileSize(TIFF* tif, uint32 nrows) uint64 TIFFTileSize64(TIFF* tif) { - return (TIFFVTileSize64(tif, tif->tif_dir.td_tilelength)); + return (TIFFVTileSize64(tif, tif->tif_dir.td_tilelength)); } tmsize_t TIFFTileSize(TIFF* tif) { - static const char module[] = "TIFFTileSize"; - uint64 m; - tmsize_t n; - m=TIFFTileSize64(tif); - n=(tmsize_t)m; - if ((uint64)n!=m) - { - TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); - n=0; - } - return(n); + static const char module[] = "TIFFTileSize"; + uint64 m; + tmsize_t n; + m=TIFFTileSize64(tif); + n=(tmsize_t)m; + if ((uint64)n!=m) + { + TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow"); + n=0; + } + return(n); } /* @@ -271,22 +294,22 @@ TIFFTileSize(TIFF* tif) void TIFFDefaultTileSize(TIFF* tif, uint32* tw, uint32* th) { - (*tif->tif_deftilesize)(tif, tw, th); + (*tif->tif_deftilesize)(tif, tw, th); } void _TIFFDefaultTileSize(TIFF* tif, uint32* tw, uint32* th) { - (void) tif; - if (*(int32*) tw < 1) - *tw = 256; - if (*(int32*) th < 1) - *th = 256; - /* roundup to a multiple of 16 per the spec */ - if (*tw & 0xf) - *tw = TIFFroundup_32(*tw, 16); - if (*th & 0xf) - *th = TIFFroundup_32(*th, 16); + (void) tif; + if (*(int32*) tw < 1) + *tw = 256; + if (*(int32*) th < 1) + *th = 256; + /* roundup to a multiple of 16 per the spec */ + if (*tw & 0xf) + *tw = TIFFroundup_32(*tw, 16); + if (*th & 0xf) + *th = TIFFroundup_32(*th, 16); } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_unix.c b/3rdparty/libtiff/tif_unix.c index ebde1bc8ba..80c437cfa3 100644 --- a/3rdparty/libtiff/tif_unix.c +++ b/3rdparty/libtiff/tif_unix.c @@ -1,4 +1,4 @@ -/* $Id: tif_unix.c,v 1.23 2012-06-01 21:40:59 fwarmerdam Exp $ */ +/* $Id: tif_unix.c,v 1.28 2017-01-11 19:02:49 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -55,56 +55,105 @@ #include "tiffiop.h" + +#define TIFF_IO_MAX 2147483647U + + +typedef union fd_as_handle_union +{ + int fd; + thandle_t h; +} fd_as_handle_union_t; + static tmsize_t _tiffReadProc(thandle_t fd, void* buf, tmsize_t size) { - size_t size_io = (size_t) size; - if ((tmsize_t) size_io != size) - { - errno=EINVAL; - return (tmsize_t) -1; - } - return ((tmsize_t) read((int) fd, buf, size_io)); + fd_as_handle_union_t fdh; + const size_t bytes_total = (size_t) size; + size_t bytes_read; + tmsize_t count = -1; + if ((tmsize_t) bytes_total != size) + { + errno=EINVAL; + return (tmsize_t) -1; + } + fdh.h = fd; + for (bytes_read=0; bytes_read < bytes_total; bytes_read+=count) + { + char *buf_offset = (char *) buf+bytes_read; + size_t io_size = bytes_total-bytes_read; + if (io_size > TIFF_IO_MAX) + io_size = TIFF_IO_MAX; + count=read(fdh.fd, buf_offset, (TIFFIOSize_t) io_size); + if (count <= 0) + break; + } + if (count < 0) + return (tmsize_t)-1; + return (tmsize_t) bytes_read; } static tmsize_t _tiffWriteProc(thandle_t fd, void* buf, tmsize_t size) { - size_t size_io = (size_t) size; - if ((tmsize_t) size_io != size) - { - errno=EINVAL; - return (tmsize_t) -1; - } - return ((tmsize_t) write((int) fd, buf, size_io)); + fd_as_handle_union_t fdh; + const size_t bytes_total = (size_t) size; + size_t bytes_written; + tmsize_t count = -1; + if ((tmsize_t) bytes_total != size) + { + errno=EINVAL; + return (tmsize_t) -1; + } + fdh.h = fd; + for (bytes_written=0; bytes_written < bytes_total; bytes_written+=count) + { + const char *buf_offset = (char *) buf+bytes_written; + size_t io_size = bytes_total-bytes_written; + if (io_size > TIFF_IO_MAX) + io_size = TIFF_IO_MAX; + count=write(fdh.fd, buf_offset, (TIFFIOSize_t) io_size); + if (count <= 0) + break; + } + if (count < 0) + return (tmsize_t)-1; + return (tmsize_t) bytes_written; + /* return ((tmsize_t) write(fdh.fd, buf, bytes_total)); */ } static uint64 _tiffSeekProc(thandle_t fd, uint64 off, int whence) { - off_t off_io = (off_t) off; - if ((uint64) off_io != off) - { - errno=EINVAL; - return (uint64) -1; /* this is really gross */ - } - return((uint64)lseek((int)fd,off_io,whence)); + fd_as_handle_union_t fdh; + _TIFF_off_t off_io = (_TIFF_off_t) off; + if ((uint64) off_io != off) + { + errno=EINVAL; + return (uint64) -1; /* this is really gross */ + } + fdh.h = fd; + return((uint64)_TIFF_lseek_f(fdh.fd,off_io,whence)); } static int _tiffCloseProc(thandle_t fd) { - return(close((int)fd)); + fd_as_handle_union_t fdh; + fdh.h = fd; + return(close(fdh.fd)); } static uint64 _tiffSizeProc(thandle_t fd) { - struct stat sb; - if (fstat((int)fd,&sb)<0) - return(0); - else - return((uint64)sb.st_size); + _TIFF_stat_s sb; + fd_as_handle_union_t fdh; + fdh.h = fd; + if (_TIFF_fstat_f(fdh.fd,&sb)<0) + return(0); + else + return((uint64)sb.st_size); } #ifdef HAVE_MMAP @@ -113,37 +162,39 @@ _tiffSizeProc(thandle_t fd) static int _tiffMapProc(thandle_t fd, void** pbase, toff_t* psize) { - uint64 size64 = _tiffSizeProc(fd); - tmsize_t sizem = (tmsize_t)size64; - if ((uint64)sizem==size64) { - *pbase = (void*) - mmap(0, (size_t)sizem, PROT_READ, MAP_SHARED, (int) fd, 0); - if (*pbase != (void*) -1) { - *psize = (tmsize_t)sizem; - return (1); - } - } - return (0); + uint64 size64 = _tiffSizeProc(fd); + tmsize_t sizem = (tmsize_t)size64; + if ((uint64)sizem==size64) { + fd_as_handle_union_t fdh; + fdh.h = fd; + *pbase = (void*) + mmap(0, (size_t)sizem, PROT_READ, MAP_SHARED, fdh.fd, 0); + if (*pbase != (void*) -1) { + *psize = (tmsize_t)sizem; + return (1); + } + } + return (0); } static void _tiffUnmapProc(thandle_t fd, void* base, toff_t size) { - (void) fd; - (void) munmap(base, (off_t) size); + (void) fd; + (void) munmap(base, (off_t) size); } #else /* !HAVE_MMAP */ static int _tiffMapProc(thandle_t fd, void** pbase, toff_t* psize) { - (void) fd; (void) pbase; (void) psize; - return (0); + (void) fd; (void) pbase; (void) psize; + return (0); } static void _tiffUnmapProc(thandle_t fd, void* base, toff_t size) { - (void) fd; (void) base; (void) size; + (void) fd; (void) base; (void) size; } #endif /* !HAVE_MMAP */ @@ -153,16 +204,18 @@ _tiffUnmapProc(thandle_t fd, void* base, toff_t size) TIFF* TIFFFdOpen(int fd, const char* name, const char* mode) { - TIFF* tif; + TIFF* tif; - tif = TIFFClientOpen(name, mode, - (thandle_t) fd, - _tiffReadProc, _tiffWriteProc, - _tiffSeekProc, _tiffCloseProc, _tiffSizeProc, - _tiffMapProc, _tiffUnmapProc); - if (tif) - tif->tif_fd = fd; - return (tif); + fd_as_handle_union_t fdh; + fdh.fd = fd; + tif = TIFFClientOpen(name, mode, + fdh.h, + _tiffReadProc, _tiffWriteProc, + _tiffSeekProc, _tiffCloseProc, _tiffSizeProc, + _tiffMapProc, _tiffUnmapProc); + if (tif) + tif->tif_fd = fd; + return (tif); } /* @@ -171,33 +224,33 @@ TIFFFdOpen(int fd, const char* name, const char* mode) TIFF* TIFFOpen(const char* name, const char* mode) { - static const char module[] = "TIFFOpen"; - int m, fd; - TIFF* tif; + static const char module[] = "TIFFOpen"; + int m, fd; + TIFF* tif; - m = _TIFFgetMode(mode, module); - if (m == -1) - return ((TIFF*)0); + m = _TIFFgetMode(mode, module); + if (m == -1) + return ((TIFF*)0); /* for cygwin and mingw */ #ifdef O_BINARY - m |= O_BINARY; + m |= O_BINARY; #endif - fd = open(name, m, 0666); - if (fd < 0) { - if (errno > 0 && strerror(errno) != NULL ) { - TIFFErrorExt(0, module, "%s: %s", name, strerror(errno) ); - } else { - TIFFErrorExt(0, module, "%s: Cannot open", name); - } - return ((TIFF *)0); - } + fd = open(name, m, 0666); + if (fd < 0) { + if (errno > 0 && strerror(errno) != NULL ) { + TIFFErrorExt(0, module, "%s: %s", name, strerror(errno) ); + } else { + TIFFErrorExt(0, module, "%s: Cannot open", name); + } + return ((TIFF *)0); + } - tif = TIFFFdOpen((int)fd, name, mode); - if(!tif) - close(fd); - return tif; + tif = TIFFFdOpen((int)fd, name, mode); + if(!tif) + close(fd); + return tif; } #ifdef __WIN32__ @@ -208,106 +261,117 @@ TIFFOpen(const char* name, const char* mode) TIFF* TIFFOpenW(const wchar_t* name, const char* mode) { - static const char module[] = "TIFFOpenW"; - int m, fd; - int mbsize; - char *mbname; - TIFF* tif; + static const char module[] = "TIFFOpenW"; + int m, fd; + int mbsize; + char *mbname; + TIFF* tif; - m = _TIFFgetMode(mode, module); - if (m == -1) - return ((TIFF*)0); + m = _TIFFgetMode(mode, module); + if (m == -1) + return ((TIFF*)0); /* for cygwin and mingw */ #ifdef O_BINARY - m |= O_BINARY; + m |= O_BINARY; #endif - fd = _wopen(name, m, 0666); - if (fd < 0) { - TIFFErrorExt(0, module, "%s: Cannot open", name); - return ((TIFF *)0); - } + fd = _wopen(name, m, 0666); + if (fd < 0) { + TIFFErrorExt(0, module, "%ls: Cannot open", name); + return ((TIFF *)0); + } - mbname = NULL; - mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL); - if (mbsize > 0) { - mbname = _TIFFmalloc(mbsize); - if (!mbname) { - TIFFErrorExt(0, module, - "Can't allocate space for filename conversion buffer"); - return ((TIFF*)0); - } + mbname = NULL; + mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL); + if (mbsize > 0) { + mbname = _TIFFmalloc(mbsize); + if (!mbname) { + TIFFErrorExt(0, module, + "Can't allocate space for filename conversion buffer"); + return ((TIFF*)0); + } - WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize, - NULL, NULL); - } + WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize, + NULL, NULL); + } - tif = TIFFFdOpen((int)fd, (mbname != NULL) ? mbname : "", - mode); - - _TIFFfree(mbname); - - if(!tif) - close(fd); - return tif; + tif = TIFFFdOpen((int)fd, (mbname != NULL) ? mbname : "", + mode); + + _TIFFfree(mbname); + + if(!tif) + close(fd); + return tif; } #endif void* _TIFFmalloc(tmsize_t s) { - return (malloc((size_t) s)); + if (s == 0) + return ((void *) NULL); + + return (malloc((size_t) s)); +} + +void* _TIFFcalloc(tmsize_t nmemb, tmsize_t siz) +{ + if( nmemb == 0 || siz == 0 ) + return ((void *) NULL); + + return calloc((size_t) nmemb, (size_t)siz); } void _TIFFfree(void* p) { - free(p); + free(p); } void* _TIFFrealloc(void* p, tmsize_t s) { - return (realloc(p, (size_t) s)); + return (realloc(p, (size_t) s)); } void _TIFFmemset(void* p, int v, tmsize_t c) { - memset(p, v, (size_t) c); + memset(p, v, (size_t) c); } void _TIFFmemcpy(void* d, const void* s, tmsize_t c) { - memcpy(d, s, (size_t) c); + memcpy(d, s, (size_t) c); } int _TIFFmemcmp(const void* p1, const void* p2, tmsize_t c) { - return (memcmp(p1, p2, (size_t) c)); + return (memcmp(p1, p2, (size_t) c)); } static void unixWarningHandler(const char* module, const char* fmt, va_list ap) { - if (module != NULL) - fprintf(stderr, "%s: ", module); - fprintf(stderr, "Warning, "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, ".\n"); + if (module != NULL) + fprintf(stderr, "%s: ", module); + fprintf(stderr, "Warning, "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); } TIFFErrorHandler _TIFFwarningHandler = unixWarningHandler; static void unixErrorHandler(const char* module, const char* fmt, va_list ap) { - if (module != NULL) - fprintf(stderr, "%s: ", module); - vfprintf(stderr, fmt, ap); - fprintf(stderr, ".\n"); + if (module != NULL) + fprintf(stderr, "%s: ", module); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); } TIFFErrorHandler _TIFFerrorHandler = unixErrorHandler; diff --git a/3rdparty/libtiff/tif_version.c b/3rdparty/libtiff/tif_version.c index f2f275d43a..f92c843d88 100644 --- a/3rdparty/libtiff/tif_version.c +++ b/3rdparty/libtiff/tif_version.c @@ -3,23 +3,23 @@ * Copyright (c) 1992-1997 Sam Leffler * Copyright (c) 1992-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #include "tiffiop.h" @@ -29,7 +29,7 @@ static const char TIFFVersion[] = TIFFLIB_VERSION_STR; const char* TIFFGetVersion(void) { - return (TIFFVersion); + return (TIFFVersion); } /* * Local Variables: diff --git a/3rdparty/libtiff/tif_warning.c b/3rdparty/libtiff/tif_warning.c index a0658a6c69..dc79f14455 100644 --- a/3rdparty/libtiff/tif_warning.c +++ b/3rdparty/libtiff/tif_warning.c @@ -1,26 +1,26 @@ -/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_warning.c,v 1.3 2010-03-10 18:56:49 bfriesen Exp $ */ +/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_warning.c,v 1.4 2017-07-04 12:54:42 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -34,41 +34,49 @@ TIFFErrorHandlerExt _TIFFwarningHandlerExt = NULL; TIFFErrorHandler TIFFSetWarningHandler(TIFFErrorHandler handler) { - TIFFErrorHandler prev = _TIFFwarningHandler; - _TIFFwarningHandler = handler; - return (prev); + TIFFErrorHandler prev = _TIFFwarningHandler; + _TIFFwarningHandler = handler; + return (prev); } TIFFErrorHandlerExt TIFFSetWarningHandlerExt(TIFFErrorHandlerExt handler) { - TIFFErrorHandlerExt prev = _TIFFwarningHandlerExt; - _TIFFwarningHandlerExt = handler; - return (prev); + TIFFErrorHandlerExt prev = _TIFFwarningHandlerExt; + _TIFFwarningHandlerExt = handler; + return (prev); } void TIFFWarning(const char* module, const char* fmt, ...) { - va_list ap; - va_start(ap, fmt); - if (_TIFFwarningHandler) - (*_TIFFwarningHandler)(module, fmt, ap); - if (_TIFFwarningHandlerExt) - (*_TIFFwarningHandlerExt)(0, module, fmt, ap); - va_end(ap); + va_list ap; + if (_TIFFwarningHandler) { + va_start(ap, fmt); + (*_TIFFwarningHandler)(module, fmt, ap); + va_end(ap); + } + if (_TIFFwarningHandlerExt) { + va_start(ap, fmt); + (*_TIFFwarningHandlerExt)(0, module, fmt, ap); + va_end(ap); + } } void TIFFWarningExt(thandle_t fd, const char* module, const char* fmt, ...) { - va_list ap; - va_start(ap, fmt); - if (_TIFFwarningHandler) - (*_TIFFwarningHandler)(module, fmt, ap); - if (_TIFFwarningHandlerExt) - (*_TIFFwarningHandlerExt)(fd, module, fmt, ap); - va_end(ap); + va_list ap; + if (_TIFFwarningHandler) { + va_start(ap, fmt); + (*_TIFFwarningHandler)(module, fmt, ap); + va_end(ap); + } + if (_TIFFwarningHandlerExt) { + va_start(ap, fmt); + (*_TIFFwarningHandlerExt)(fd, module, fmt, ap); + va_end(ap); + } } diff --git a/3rdparty/libtiff/tif_win32.c b/3rdparty/libtiff/tif_win32.c index 73b8175ff8..090baed871 100644 --- a/3rdparty/libtiff/tif_win32.c +++ b/3rdparty/libtiff/tif_win32.c @@ -1,26 +1,26 @@ -/* $Id: tif_win32.c,v 1.39 2011-12-22 17:07:57 bfriesen Exp $ */ +/* $Id: tif_win32.c,v 1.42 2017-01-11 19:02:49 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -28,6 +28,31 @@ * TIFF Library Win32-specific Routines. Adapted from tif_unix.c 4/5/95 by * Scott Wagner (wagner@itek.com), Itek Graphix, Rochester, NY USA */ + +/* + CreateFileA/CreateFileW return type 'HANDLE'. + + thandle_t is declared like + + DECLARE_HANDLE(thandle_t); + + in tiffio.h. + + Windows (from winnt.h) DECLARE_HANDLE logic looks like + + #ifdef STRICT + typedef void *HANDLE; + #define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name + #else + typedef PVOID HANDLE; + #define DECLARE_HANDLE(name) typedef HANDLE name + #endif + + See http://bugzilla.maptools.org/show_bug.cgi?id=1941 for problems in WIN64 + builds resulting from this. Unfortunately, the proposed patch was lost. + +*/ + #include "tiffiop.h" #include @@ -35,111 +60,111 @@ static tmsize_t _tiffReadProc(thandle_t fd, void* buf, tmsize_t size) { - /* tmsize_t is 64bit on 64bit systems, but the WinAPI ReadFile takes - * 32bit sizes, so we loop through the data in suitable 32bit sized - * chunks */ - uint8* ma; - uint64 mb; - DWORD n; - DWORD o; - tmsize_t p; - ma=(uint8*)buf; - mb=size; - p=0; - while (mb>0) - { - n=0x80000000UL; - if ((uint64)n>mb) - n=(DWORD)mb; - if (!ReadFile(fd,(LPVOID)ma,n,&o,NULL)) - return(0); - ma+=o; - mb-=o; - p+=o; - if (o!=n) - break; - } - return(p); + /* tmsize_t is 64bit on 64bit systems, but the WinAPI ReadFile takes + * 32bit sizes, so we loop through the data in suitable 32bit sized + * chunks */ + uint8* ma; + uint64 mb; + DWORD n; + DWORD o; + tmsize_t p; + ma=(uint8*)buf; + mb=size; + p=0; + while (mb>0) + { + n=0x80000000UL; + if ((uint64)n>mb) + n=(DWORD)mb; + if (!ReadFile(fd,(LPVOID)ma,n,&o,NULL)) + return(0); + ma+=o; + mb-=o; + p+=o; + if (o!=n) + break; + } + return(p); } static tmsize_t _tiffWriteProc(thandle_t fd, void* buf, tmsize_t size) { - /* tmsize_t is 64bit on 64bit systems, but the WinAPI WriteFile takes - * 32bit sizes, so we loop through the data in suitable 32bit sized - * chunks */ - uint8* ma; - uint64 mb; - DWORD n; - DWORD o; - tmsize_t p; - ma=(uint8*)buf; - mb=size; - p=0; - while (mb>0) - { - n=0x80000000UL; - if ((uint64)n>mb) - n=(DWORD)mb; - if (!WriteFile(fd,(LPVOID)ma,n,&o,NULL)) - return(0); - ma+=o; - mb-=o; - p+=o; - if (o!=n) - break; - } - return(p); + /* tmsize_t is 64bit on 64bit systems, but the WinAPI WriteFile takes + * 32bit sizes, so we loop through the data in suitable 32bit sized + * chunks */ + uint8* ma; + uint64 mb; + DWORD n; + DWORD o; + tmsize_t p; + ma=(uint8*)buf; + mb=size; + p=0; + while (mb>0) + { + n=0x80000000UL; + if ((uint64)n>mb) + n=(DWORD)mb; + if (!WriteFile(fd,(LPVOID)ma,n,&o,NULL)) + return(0); + ma+=o; + mb-=o; + p+=o; + if (o!=n) + break; + } + return(p); } static uint64 _tiffSeekProc(thandle_t fd, uint64 off, int whence) { - LARGE_INTEGER offli; - DWORD dwMoveMethod; - offli.QuadPart = off; - switch(whence) - { - case SEEK_SET: - dwMoveMethod = FILE_BEGIN; - break; - case SEEK_CUR: - dwMoveMethod = FILE_CURRENT; - break; - case SEEK_END: - dwMoveMethod = FILE_END; - break; - default: - dwMoveMethod = FILE_BEGIN; - break; - } - offli.LowPart=SetFilePointer(fd,offli.LowPart,&offli.HighPart,dwMoveMethod); - if ((offli.LowPart==INVALID_SET_FILE_POINTER)&&(GetLastError()!=NO_ERROR)) - offli.QuadPart=0; - return(offli.QuadPart); + LARGE_INTEGER offli; + DWORD dwMoveMethod; + offli.QuadPart = off; + switch(whence) + { + case SEEK_SET: + dwMoveMethod = FILE_BEGIN; + break; + case SEEK_CUR: + dwMoveMethod = FILE_CURRENT; + break; + case SEEK_END: + dwMoveMethod = FILE_END; + break; + default: + dwMoveMethod = FILE_BEGIN; + break; + } + offli.LowPart=SetFilePointer(fd,offli.LowPart,&offli.HighPart,dwMoveMethod); + if ((offli.LowPart==INVALID_SET_FILE_POINTER)&&(GetLastError()!=NO_ERROR)) + offli.QuadPart=0; + return(offli.QuadPart); } static int _tiffCloseProc(thandle_t fd) { - return (CloseHandle(fd) ? 0 : -1); + return (CloseHandle(fd) ? 0 : -1); } static uint64 _tiffSizeProc(thandle_t fd) { - ULARGE_INTEGER m; - m.LowPart=GetFileSize(fd,&m.HighPart); - return(m.QuadPart); + ULARGE_INTEGER m; + m.LowPart=GetFileSize(fd,&m.HighPart); + return(m.QuadPart); } static int _tiffDummyMapProc(thandle_t fd, void** pbase, toff_t* psize) { - (void) fd; - (void) pbase; - (void) psize; - return (0); + (void) fd; + (void) pbase; + (void) psize; + return (0); } /* @@ -156,42 +181,42 @@ _tiffDummyMapProc(thandle_t fd, void** pbase, toff_t* psize) static int _tiffMapProc(thandle_t fd, void** pbase, toff_t* psize) { - uint64 size; - tmsize_t sizem; - HANDLE hMapFile; + uint64 size; + tmsize_t sizem; + HANDLE hMapFile; - size = _tiffSizeProc(fd); - sizem = (tmsize_t)size; - if ((uint64)sizem!=size) - return (0); + size = _tiffSizeProc(fd); + sizem = (tmsize_t)size; + if ((uint64)sizem!=size) + return (0); - /* By passing in 0 for the maximum file size, it specifies that we - create a file mapping object for the full file size. */ - hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, 0, NULL); - if (hMapFile == NULL) - return (0); - *pbase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); - CloseHandle(hMapFile); - if (*pbase == NULL) - return (0); - *psize = size; - return(1); + /* By passing in 0 for the maximum file size, it specifies that we + create a file mapping object for the full file size. */ + hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, 0, NULL); + if (hMapFile == NULL) + return (0); + *pbase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); + CloseHandle(hMapFile); + if (*pbase == NULL) + return (0); + *psize = size; + return(1); } static void _tiffDummyUnmapProc(thandle_t fd, void* base, toff_t size) { - (void) fd; - (void) base; - (void) size; + (void) fd; + (void) base; + (void) size; } static void _tiffUnmapProc(thandle_t fd, void* base, toff_t size) { - (void) fd; - (void) size; - UnmapViewOfFile(base); + (void) fd; + (void) size; + UnmapViewOfFile(base); } /* @@ -202,26 +227,26 @@ _tiffUnmapProc(thandle_t fd, void* base, toff_t size) TIFF* TIFFFdOpen(int ifd, const char* name, const char* mode) { - TIFF* tif; - int fSuppressMap; - int m; - fSuppressMap=0; - for (m=0; mode[m]!=0; m++) - { - if (mode[m]=='u') - { - fSuppressMap=1; - break; - } - } - tif = TIFFClientOpen(name, mode, (thandle_t)ifd, - _tiffReadProc, _tiffWriteProc, - _tiffSeekProc, _tiffCloseProc, _tiffSizeProc, - fSuppressMap ? _tiffDummyMapProc : _tiffMapProc, - fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc); - if (tif) - tif->tif_fd = ifd; - return (tif); + TIFF* tif; + int fSuppressMap; + int m; + fSuppressMap=0; + for (m=0; mode[m]!=0; m++) + { + if (mode[m]=='u') + { + fSuppressMap=1; + break; + } + } + tif = TIFFClientOpen(name, mode, (thandle_t)ifd, /* FIXME: WIN64 cast to pointer warning */ + _tiffReadProc, _tiffWriteProc, + _tiffSeekProc, _tiffCloseProc, _tiffSizeProc, + fSuppressMap ? _tiffDummyMapProc : _tiffMapProc, + fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc); + if (tif) + tif->tif_fd = ifd; + return (tif); } #ifndef _WIN32_WCE @@ -232,37 +257,37 @@ TIFFFdOpen(int ifd, const char* name, const char* mode) TIFF* TIFFOpen(const char* name, const char* mode) { - static const char module[] = "TIFFOpen"; - thandle_t fd; - int m; - DWORD dwMode; - TIFF* tif; + static const char module[] = "TIFFOpen"; + thandle_t fd; + int m; + DWORD dwMode; + TIFF* tif; - m = _TIFFgetMode(mode, module); + m = _TIFFgetMode(mode, module); - switch(m) { - case O_RDONLY: dwMode = OPEN_EXISTING; break; - case O_RDWR: dwMode = OPEN_ALWAYS; break; - case O_RDWR|O_CREAT: dwMode = OPEN_ALWAYS; break; - case O_RDWR|O_TRUNC: dwMode = CREATE_ALWAYS; break; - case O_RDWR|O_CREAT|O_TRUNC: dwMode = CREATE_ALWAYS; break; - default: return ((TIFF*)0); - } + switch(m) { + case O_RDONLY: dwMode = OPEN_EXISTING; break; + case O_RDWR: dwMode = OPEN_ALWAYS; break; + case O_RDWR|O_CREAT: dwMode = OPEN_ALWAYS; break; + case O_RDWR|O_TRUNC: dwMode = CREATE_ALWAYS; break; + case O_RDWR|O_CREAT|O_TRUNC: dwMode = CREATE_ALWAYS; break; + default: return ((TIFF*)0); + } + + fd = (thandle_t)CreateFileA(name, + (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE), + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode, + (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL, + NULL); + if (fd == INVALID_HANDLE_VALUE) { + TIFFErrorExt(0, module, "%s: Cannot open", name); + return ((TIFF *)0); + } - fd = (thandle_t)CreateFileA(name, - (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE), - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode, - (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL, - NULL); - if (fd == INVALID_HANDLE_VALUE) { - TIFFErrorExt(0, module, "%s: Cannot open", name); - return ((TIFF *)0); - } - - tif = TIFFFdOpen((int)fd, name, mode); - if(!tif) - CloseHandle(fd); - return tif; + tif = TIFFFdOpen((int)fd, name, mode); /* FIXME: WIN64 cast from pointer to int warning */ + if(!tif) + CloseHandle(fd); + return tif; } /* @@ -271,57 +296,57 @@ TIFFOpen(const char* name, const char* mode) TIFF* TIFFOpenW(const wchar_t* name, const char* mode) { - static const char module[] = "TIFFOpenW"; - thandle_t fd; - int m; - DWORD dwMode; - int mbsize; - char *mbname; - TIFF *tif; + static const char module[] = "TIFFOpenW"; + thandle_t fd; + int m; + DWORD dwMode; + int mbsize; + char *mbname; + TIFF *tif; - m = _TIFFgetMode(mode, module); + m = _TIFFgetMode(mode, module); - switch(m) { - case O_RDONLY: dwMode = OPEN_EXISTING; break; - case O_RDWR: dwMode = OPEN_ALWAYS; break; - case O_RDWR|O_CREAT: dwMode = OPEN_ALWAYS; break; - case O_RDWR|O_TRUNC: dwMode = CREATE_ALWAYS; break; - case O_RDWR|O_CREAT|O_TRUNC: dwMode = CREATE_ALWAYS; break; - default: return ((TIFF*)0); - } + switch(m) { + case O_RDONLY: dwMode = OPEN_EXISTING; break; + case O_RDWR: dwMode = OPEN_ALWAYS; break; + case O_RDWR|O_CREAT: dwMode = OPEN_ALWAYS; break; + case O_RDWR|O_TRUNC: dwMode = CREATE_ALWAYS; break; + case O_RDWR|O_CREAT|O_TRUNC: dwMode = CREATE_ALWAYS; break; + default: return ((TIFF*)0); + } - fd = (thandle_t)CreateFileW(name, - (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE), - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode, - (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL, - NULL); - if (fd == INVALID_HANDLE_VALUE) { - TIFFErrorExt(0, module, "%S: Cannot open", name); - return ((TIFF *)0); - } + fd = (thandle_t)CreateFileW(name, + (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE), + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode, + (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL, + NULL); + if (fd == INVALID_HANDLE_VALUE) { + TIFFErrorExt(0, module, "%S: Cannot open", name); + return ((TIFF *)0); + } - mbname = NULL; - mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL); - if (mbsize > 0) { - mbname = (char *)_TIFFmalloc(mbsize); - if (!mbname) { - TIFFErrorExt(0, module, - "Can't allocate space for filename conversion buffer"); - return ((TIFF*)0); - } + mbname = NULL; + mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL); + if (mbsize > 0) { + mbname = (char *)_TIFFmalloc(mbsize); + if (!mbname) { + TIFFErrorExt(0, module, + "Can't allocate space for filename conversion buffer"); + return ((TIFF*)0); + } - WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize, - NULL, NULL); - } + WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize, + NULL, NULL); + } - tif = TIFFFdOpen((int)fd, - (mbname != NULL) ? mbname : "", mode); - if(!tif) - CloseHandle(fd); + tif = TIFFFdOpen((int)fd, /* FIXME: WIN64 cast from pointer to int warning */ + (mbname != NULL) ? mbname : "", mode); + if(!tif) + CloseHandle(fd); - _TIFFfree(mbname); + _TIFFfree(mbname); - return tif; + return tif; } #endif /* ndef _WIN32_WCE */ @@ -329,37 +354,48 @@ TIFFOpenW(const wchar_t* name, const char* mode) void* _TIFFmalloc(tmsize_t s) { - return (malloc((size_t) s)); + if (s == 0) + return ((void *) NULL); + + return (malloc((size_t) s)); +} + +void* _TIFFcalloc(tmsize_t nmemb, tmsize_t siz) +{ + if( nmemb == 0 || siz == 0 ) + return ((void *) NULL); + + return calloc((size_t) nmemb, (size_t)siz); } void _TIFFfree(void* p) { - free(p); + free(p); } void* _TIFFrealloc(void* p, tmsize_t s) { - return (realloc(p, (size_t) s)); + return (realloc(p, (size_t) s)); } void _TIFFmemset(void* p, int v, tmsize_t c) { - memset(p, v, (size_t) c); + memset(p, v, (size_t) c); } void _TIFFmemcpy(void* d, const void* s, tmsize_t c) { - memcpy(d, s, (size_t) c); + memcpy(d, s, (size_t) c); } int _TIFFmemcmp(const void* p1, const void* p2, tmsize_t c) { - return (memcmp(p1, p2, (size_t) c)); + return (memcmp(p1, p2, (size_t) c)); } #ifndef _WIN32_WCE @@ -372,30 +408,30 @@ static void Win32WarningHandler(const char* module, const char* fmt, va_list ap) { #ifndef TIF_PLATFORM_CONSOLE - LPTSTR szTitle; - LPTSTR szTmp; - LPCTSTR szTitleText = "%s Warning"; - LPCTSTR szDefaultModule = "LIBTIFF"; - LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module; + LPTSTR szTitle; + LPTSTR szTmp; + LPCTSTR szTitleText = "%s Warning"; + LPCTSTR szDefaultModule = "LIBTIFF"; + LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module; SIZE_T nBufSize = (strlen(szTmpModule) + strlen(szTitleText) + strlen(fmt) + 256)*sizeof(char); - if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, nBufSize)) == NULL) - return; - sprintf(szTitle, szTitleText, szTmpModule); - szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char); - vsnprintf(szTmp, nBufSize-(strlen(szTitle)+2)*sizeof(char), fmt, ap); - MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION); - LocalFree(szTitle); + if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, nBufSize)) == NULL) + return; + sprintf(szTitle, szTitleText, szTmpModule); + szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char); + vsnprintf(szTmp, nBufSize-(strlen(szTitle)+2)*sizeof(char), fmt, ap); + MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION); + LocalFree(szTitle); - return; + return; #else - if (module != NULL) - fprintf(stderr, "%s: ", module); - fprintf(stderr, "Warning, "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, ".\n"); -#endif + if (module != NULL) + fprintf(stderr, "%s: ", module); + fprintf(stderr, "Warning, "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +#endif } TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler; @@ -403,28 +439,28 @@ static void Win32ErrorHandler(const char* module, const char* fmt, va_list ap) { #ifndef TIF_PLATFORM_CONSOLE - LPTSTR szTitle; - LPTSTR szTmp; - LPCTSTR szTitleText = "%s Error"; - LPCTSTR szDefaultModule = "LIBTIFF"; - LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module; + LPTSTR szTitle; + LPTSTR szTmp; + LPCTSTR szTitleText = "%s Error"; + LPCTSTR szDefaultModule = "LIBTIFF"; + LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module; SIZE_T nBufSize = (strlen(szTmpModule) + strlen(szTitleText) + strlen(fmt) + 256)*sizeof(char); - if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, nBufSize)) == NULL) - return; - sprintf(szTitle, szTitleText, szTmpModule); - szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char); - vsnprintf(szTmp, nBufSize-(strlen(szTitle)+2)*sizeof(char), fmt, ap); - MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION); - LocalFree(szTitle); - return; + if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, nBufSize)) == NULL) + return; + sprintf(szTitle, szTitleText, szTmpModule); + szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char); + vsnprintf(szTmp, nBufSize-(strlen(szTitle)+2)*sizeof(char), fmt, ap); + MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION); + LocalFree(szTitle); + return; #else - if (module != NULL) - fprintf(stderr, "%s: ", module); - vfprintf(stderr, fmt, ap); - fprintf(stderr, ".\n"); -#endif + if (module != NULL) + fprintf(stderr, "%s: ", module); + vfprintf(stderr, fmt, ap); + fprintf(stderr, ".\n"); +#endif } TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler; diff --git a/3rdparty/libtiff/tif_write.c b/3rdparty/libtiff/tif_write.c index b7fffdeda6..4c216ec200 100644 --- a/3rdparty/libtiff/tif_write.c +++ b/3rdparty/libtiff/tif_write.c @@ -1,4 +1,4 @@ -/* $Id: tif_write.c,v 1.36 2011-02-18 20:53:04 fwarmerdam Exp $ */ +/* $Id: tif_write.c,v 1.46 2016-12-03 21:57:44 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -35,12 +35,12 @@ #define STRIPINCR 20 /* expansion factor on strip array */ #define WRITECHECKSTRIPS(tif, module) \ - (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module)) + (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module)) #define WRITECHECKTILES(tif, module) \ - (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module)) + (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module)) #define BUFFERCHECK(tif) \ - ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) || \ - TIFFWriteBufferSetup((tif), NULL, (tmsize_t) -1)) + ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) || \ + TIFFWriteBufferSetup((tif), NULL, (tmsize_t) -1)) static int TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module); static int TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc); @@ -48,130 +48,134 @@ static int TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc); int TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample) { - static const char module[] = "TIFFWriteScanline"; - register TIFFDirectory *td; - int status, imagegrew = 0; - uint32 strip; + static const char module[] = "TIFFWriteScanline"; + register TIFFDirectory *td; + int status, imagegrew = 0; + uint32 strip; - if (!WRITECHECKSTRIPS(tif, module)) - return (-1); - /* - * Handle delayed allocation of data buffer. This - * permits it to be sized more intelligently (using - * directory information). - */ - if (!BUFFERCHECK(tif)) - return (-1); + if (!WRITECHECKSTRIPS(tif, module)) + return (-1); + /* + * Handle delayed allocation of data buffer. This + * permits it to be sized more intelligently (using + * directory information). + */ + if (!BUFFERCHECK(tif)) + return (-1); tif->tif_flags |= TIFF_BUF4WRITE; /* not strictly sure this is right*/ - td = &tif->tif_dir; - /* - * Extend image length if needed - * (but only for PlanarConfig=1). - */ - if (row >= td->td_imagelength) { /* extend image */ - if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { - TIFFErrorExt(tif->tif_clientdata, module, - "Can not change \"ImageLength\" when using separate planes"); - return (-1); - } - td->td_imagelength = row+1; - imagegrew = 1; - } - /* - * Calculate strip and check for crossings. - */ - if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { - if (sample >= td->td_samplesperpixel) { - TIFFErrorExt(tif->tif_clientdata, module, - "%lu: Sample out of range, max %lu", - (unsigned long) sample, (unsigned long) td->td_samplesperpixel); - return (-1); - } - strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; - } else - strip = row / td->td_rowsperstrip; - /* - * Check strip array to make sure there's space. We don't support - * dynamically growing files that have data organized in separate - * bitplanes because it's too painful. In that case we require that - * the imagelength be set properly before the first write (so that the - * strips array will be fully allocated above). - */ - if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module)) - return (-1); - if (strip != tif->tif_curstrip) { - /* - * Changing strips -- flush any data present. - */ - if (!TIFFFlushData(tif)) - return (-1); - tif->tif_curstrip = strip; - /* - * Watch out for a growing image. The value of strips/image - * will initially be 1 (since it can't be deduced until the - * imagelength is known). - */ - if (strip >= td->td_stripsperimage && imagegrew) - td->td_stripsperimage = - TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip); - tif->tif_row = - (strip % td->td_stripsperimage) * td->td_rowsperstrip; - if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { - if (!(*tif->tif_setupencode)(tif)) - return (-1); - tif->tif_flags |= TIFF_CODERSETUP; - } + td = &tif->tif_dir; + /* + * Extend image length if needed + * (but only for PlanarConfig=1). + */ + if (row >= td->td_imagelength) { /* extend image */ + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + TIFFErrorExt(tif->tif_clientdata, module, + "Can not change \"ImageLength\" when using separate planes"); + return (-1); + } + td->td_imagelength = row+1; + imagegrew = 1; + } + /* + * Calculate strip and check for crossings. + */ + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + if (sample >= td->td_samplesperpixel) { + TIFFErrorExt(tif->tif_clientdata, module, + "%lu: Sample out of range, max %lu", + (unsigned long) sample, (unsigned long) td->td_samplesperpixel); + return (-1); + } + strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip; + } else + strip = row / td->td_rowsperstrip; + /* + * Check strip array to make sure there's space. We don't support + * dynamically growing files that have data organized in separate + * bitplanes because it's too painful. In that case we require that + * the imagelength be set properly before the first write (so that the + * strips array will be fully allocated above). + */ + if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module)) + return (-1); + if (strip != tif->tif_curstrip) { + /* + * Changing strips -- flush any data present. + */ + if (!TIFFFlushData(tif)) + return (-1); + tif->tif_curstrip = strip; + /* + * Watch out for a growing image. The value of strips/image + * will initially be 1 (since it can't be deduced until the + * imagelength is known). + */ + if (strip >= td->td_stripsperimage && imagegrew) + td->td_stripsperimage = + TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip); + if (td->td_stripsperimage == 0) { + TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image"); + return (-1); + } + tif->tif_row = + (strip % td->td_stripsperimage) * td->td_rowsperstrip; + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupencode)(tif)) + return (-1); + tif->tif_flags |= TIFF_CODERSETUP; + } + + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; - tif->tif_rawcc = 0; - tif->tif_rawcp = tif->tif_rawdata; + if( td->td_stripbytecount[strip] > 0 ) + { + /* if we are writing over existing tiles, zero length */ + td->td_stripbytecount[strip] = 0; - if( td->td_stripbytecount[strip] > 0 ) - { - /* if we are writing over existing tiles, zero length */ - td->td_stripbytecount[strip] = 0; + /* this forces TIFFAppendToStrip() to do a seek */ + tif->tif_curoff = 0; + } - /* this forces TIFFAppendToStrip() to do a seek */ - tif->tif_curoff = 0; - } + if (!(*tif->tif_preencode)(tif, sample)) + return (-1); + tif->tif_flags |= TIFF_POSTENCODE; + } + /* + * Ensure the write is either sequential or at the + * beginning of a strip (or that we can randomly + * access the data -- i.e. no encoding). + */ + if (row != tif->tif_row) { + if (row < tif->tif_row) { + /* + * Moving backwards within the same strip: + * backup to the start and then decode + * forward (below). + */ + tif->tif_row = (strip % td->td_stripsperimage) * + td->td_rowsperstrip; + tif->tif_rawcp = tif->tif_rawdata; + } + /* + * Seek forward to the desired row. + */ + if (!(*tif->tif_seek)(tif, row - tif->tif_row)) + return (-1); + tif->tif_row = row; + } - if (!(*tif->tif_preencode)(tif, sample)) - return (-1); - tif->tif_flags |= TIFF_POSTENCODE; - } - /* - * Ensure the write is either sequential or at the - * beginning of a strip (or that we can randomly - * access the data -- i.e. no encoding). - */ - if (row != tif->tif_row) { - if (row < tif->tif_row) { - /* - * Moving backwards within the same strip: - * backup to the start and then decode - * forward (below). - */ - tif->tif_row = (strip % td->td_stripsperimage) * - td->td_rowsperstrip; - tif->tif_rawcp = tif->tif_rawdata; - } - /* - * Seek forward to the desired row. - */ - if (!(*tif->tif_seek)(tif, row - tif->tif_row)) - return (-1); - tif->tif_row = row; - } + /* swab if needed - note that source buffer will be altered */ + tif->tif_postdecode( tif, (uint8*) buf, tif->tif_scanlinesize ); - /* swab if needed - note that source buffer will be altered */ - tif->tif_postdecode( tif, (uint8*) buf, tif->tif_scanlinesize ); - - status = (*tif->tif_encoderow)(tif, (uint8*) buf, - tif->tif_scanlinesize, sample); + status = (*tif->tif_encoderow)(tif, (uint8*) buf, + tif->tif_scanlinesize, sample); /* we are now poised at the beginning of the next row */ - tif->tif_row = row + 1; - return (status); + tif->tif_row = row + 1; + return (status); } /* @@ -183,81 +187,114 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample) tmsize_t TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) { - static const char module[] = "TIFFWriteEncodedStrip"; - TIFFDirectory *td = &tif->tif_dir; - uint16 sample; + static const char module[] = "TIFFWriteEncodedStrip"; + TIFFDirectory *td = &tif->tif_dir; + uint16 sample; - if (!WRITECHECKSTRIPS(tif, module)) - return ((tmsize_t) -1); - /* - * Check strip array to make sure there's space. - * We don't support dynamically growing files that - * have data organized in separate bitplanes because - * it's too painful. In that case we require that - * the imagelength be set properly before the first - * write (so that the strips array will be fully - * allocated above). - */ - if (strip >= td->td_nstrips) { - if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { - TIFFErrorExt(tif->tif_clientdata, module, - "Can not grow image by strips when using separate planes"); - return ((tmsize_t) -1); - } - if (!TIFFGrowStrips(tif, 1, module)) - return ((tmsize_t) -1); - td->td_stripsperimage = - TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip); - } - /* - * Handle delayed allocation of data buffer. This - * permits it to be sized according to the directory - * info. - */ - if (!BUFFERCHECK(tif)) - return ((tmsize_t) -1); + if (!WRITECHECKSTRIPS(tif, module)) + return ((tmsize_t) -1); + /* + * Check strip array to make sure there's space. + * We don't support dynamically growing files that + * have data organized in separate bitplanes because + * it's too painful. In that case we require that + * the imagelength be set properly before the first + * write (so that the strips array will be fully + * allocated above). + */ + if (strip >= td->td_nstrips) { + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + TIFFErrorExt(tif->tif_clientdata, module, + "Can not grow image by strips when using separate planes"); + return ((tmsize_t) -1); + } + if (!TIFFGrowStrips(tif, 1, module)) + return ((tmsize_t) -1); + td->td_stripsperimage = + TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip); + } + /* + * Handle delayed allocation of data buffer. This + * permits it to be sized according to the directory + * info. + */ + if (!BUFFERCHECK(tif)) + return ((tmsize_t) -1); tif->tif_flags |= TIFF_BUF4WRITE; - tif->tif_curstrip = strip; + tif->tif_curstrip = strip; - tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; - if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { - if (!(*tif->tif_setupencode)(tif)) - return ((tmsize_t) -1); - tif->tif_flags |= TIFF_CODERSETUP; - } + if (td->td_stripsperimage == 0) { + TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image"); + return ((tmsize_t) -1); + } - tif->tif_rawcc = 0; - tif->tif_rawcp = tif->tif_rawdata; + tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupencode)(tif)) + return ((tmsize_t) -1); + tif->tif_flags |= TIFF_CODERSETUP; + } - if( td->td_stripbytecount[strip] > 0 ) + if( td->td_stripbytecount[strip] > 0 ) { - /* Force TIFFAppendToStrip() to consider placing data at end + /* Make sure that at the first attempt of rewriting the tile, we will have */ + /* more bytes available in the output buffer than the previous byte count, */ + /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */ + /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */ + if( tif->tif_rawdatasize <= (tmsize_t)td->td_stripbytecount[strip] ) + { + if( !(TIFFWriteBufferSetup(tif, NULL, + (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[strip] + 1), 1024))) ) + return ((tmsize_t)(-1)); + } + + /* Force TIFFAppendToStrip() to consider placing data at end of file. */ tif->tif_curoff = 0; } - tif->tif_flags &= ~TIFF_POSTENCODE; - sample = (uint16)(strip / td->td_stripsperimage); - if (!(*tif->tif_preencode)(tif, sample)) - return ((tmsize_t) -1); - - /* swab if needed - note that source buffer will be altered */ - tif->tif_postdecode( tif, (uint8*) data, cc ); - - if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample)) - return (0); - if (!(*tif->tif_postencode)(tif)) - return ((tmsize_t) -1); - if (!isFillOrder(tif, td->td_fillorder) && - (tif->tif_flags & TIFF_NOBITREV) == 0) - TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc); - if (tif->tif_rawcc > 0 && - !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc)) - return ((tmsize_t) -1); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; - return (cc); + + tif->tif_flags &= ~TIFF_POSTENCODE; + + /* shortcut to avoid an extra memcpy() */ + if( td->td_compression == COMPRESSION_NONE ) + { + /* swab if needed - note that source buffer will be altered */ + tif->tif_postdecode( tif, (uint8*) data, cc ); + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits((uint8*) data, cc); + + if (cc > 0 && + !TIFFAppendToStrip(tif, strip, (uint8*) data, cc)) + return ((tmsize_t) -1); + return (cc); + } + + sample = (uint16)(strip / td->td_stripsperimage); + if (!(*tif->tif_preencode)(tif, sample)) + return ((tmsize_t) -1); + + /* swab if needed - note that source buffer will be altered */ + tif->tif_postdecode( tif, (uint8*) data, cc ); + + if (!(*tif->tif_encodestrip)(tif, (uint8*) data, cc, sample)) + return ((tmsize_t) -1); + if (!(*tif->tif_postencode)(tif)) + return ((tmsize_t) -1); + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc); + if (tif->tif_rawcc > 0 && + !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc)) + return ((tmsize_t) -1); + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + return (cc); } /* @@ -268,41 +305,45 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) tmsize_t TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) { - static const char module[] = "TIFFWriteRawStrip"; - TIFFDirectory *td = &tif->tif_dir; + static const char module[] = "TIFFWriteRawStrip"; + TIFFDirectory *td = &tif->tif_dir; - if (!WRITECHECKSTRIPS(tif, module)) - return ((tmsize_t) -1); - /* - * Check strip array to make sure there's space. - * We don't support dynamically growing files that - * have data organized in separate bitplanes because - * it's too painful. In that case we require that - * the imagelength be set properly before the first - * write (so that the strips array will be fully - * allocated above). - */ - if (strip >= td->td_nstrips) { - if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { - TIFFErrorExt(tif->tif_clientdata, module, - "Can not grow image by strips when using separate planes"); - return ((tmsize_t) -1); + if (!WRITECHECKSTRIPS(tif, module)) + return ((tmsize_t) -1); + /* + * Check strip array to make sure there's space. + * We don't support dynamically growing files that + * have data organized in separate bitplanes because + * it's too painful. In that case we require that + * the imagelength be set properly before the first + * write (so that the strips array will be fully + * allocated above). + */ + if (strip >= td->td_nstrips) { + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { + TIFFErrorExt(tif->tif_clientdata, module, + "Can not grow image by strips when using separate planes"); + return ((tmsize_t) -1); + } + /* + * Watch out for a growing image. The value of + * strips/image will initially be 1 (since it + * can't be deduced until the imagelength is known). + */ + if (strip >= td->td_stripsperimage) + td->td_stripsperimage = + TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip); + if (!TIFFGrowStrips(tif, 1, module)) + return ((tmsize_t) -1); + } + tif->tif_curstrip = strip; + if (td->td_stripsperimage == 0) { + TIFFErrorExt(tif->tif_clientdata, module,"Zero strips per image"); + return ((tmsize_t) -1); } - /* - * Watch out for a growing image. The value of - * strips/image will initially be 1 (since it - * can't be deduced until the imagelength is known). - */ - if (strip >= td->td_stripsperimage) - td->td_stripsperimage = - TIFFhowmany_32(td->td_imagelength,td->td_rowsperstrip); - if (!TIFFGrowStrips(tif, 1, module)) - return ((tmsize_t) -1); - } - tif->tif_curstrip = strip; - tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; - return (TIFFAppendToStrip(tif, strip, (uint8*) data, cc) ? - cc : (tmsize_t) -1); + tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip; + return (TIFFAppendToStrip(tif, strip, (uint8*) data, cc) ? + cc : (tmsize_t) -1); } /* @@ -312,16 +353,16 @@ TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) tmsize_t TIFFWriteTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s) { - if (!TIFFCheckTile(tif, x, y, z, s)) - return ((tmsize_t)(-1)); - /* - * NB: A tile size of -1 is used instead of tif_tilesize knowing - * that TIFFWriteEncodedTile will clamp this to the tile size. - * This is done because the tile size may not be defined until - * after the output buffer is setup in TIFFWriteBufferSetup. - */ - return (TIFFWriteEncodedTile(tif, - TIFFComputeTile(tif, x, y, z, s), buf, (tmsize_t)(-1))); + if (!TIFFCheckTile(tif, x, y, z, s)) + return ((tmsize_t)(-1)); + /* + * NB: A tile size of -1 is used instead of tif_tilesize knowing + * that TIFFWriteEncodedTile will clamp this to the tile size. + * This is done because the tile size may not be defined until + * after the output buffer is setup in TIFFWriteBufferSetup. + */ + return (TIFFWriteEncodedTile(tif, + TIFFComputeTile(tif, x, y, z, s), buf, (tmsize_t)(-1))); } /* @@ -339,78 +380,115 @@ TIFFWriteTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s) tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) { - static const char module[] = "TIFFWriteEncodedTile"; - TIFFDirectory *td; - uint16 sample; + static const char module[] = "TIFFWriteEncodedTile"; + TIFFDirectory *td; + uint16 sample; + uint32 howmany32; - if (!WRITECHECKTILES(tif, module)) - return ((tmsize_t)(-1)); - td = &tif->tif_dir; - if (tile >= td->td_nstrips) { - TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu", - (unsigned long) tile, (unsigned long) td->td_nstrips); - return ((tmsize_t)(-1)); - } - /* - * Handle delayed allocation of data buffer. This - * permits it to be sized more intelligently (using - * directory information). - */ - if (!BUFFERCHECK(tif)) - return ((tmsize_t)(-1)); + if (!WRITECHECKTILES(tif, module)) + return ((tmsize_t)(-1)); + td = &tif->tif_dir; + if (tile >= td->td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu", + (unsigned long) tile, (unsigned long) td->td_nstrips); + return ((tmsize_t)(-1)); + } + /* + * Handle delayed allocation of data buffer. This + * permits it to be sized more intelligently (using + * directory information). + */ + if (!BUFFERCHECK(tif)) + return ((tmsize_t)(-1)); tif->tif_flags |= TIFF_BUF4WRITE; - tif->tif_curtile = tile; + tif->tif_curtile = tile; - tif->tif_rawcc = 0; - tif->tif_rawcp = tif->tif_rawdata; - - if( td->td_stripbytecount[tile] > 0 ) + if( td->td_stripbytecount[tile] > 0 ) { - /* Force TIFFAppendToStrip() to consider placing data at end + /* Make sure that at the first attempt of rewriting the tile, we will have */ + /* more bytes available in the output buffer than the previous byte count, */ + /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */ + /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */ + if( tif->tif_rawdatasize <= (tmsize_t) td->td_stripbytecount[tile] ) + { + if( !(TIFFWriteBufferSetup(tif, NULL, + (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[tile] + 1), 1024))) ) + return ((tmsize_t)(-1)); + } + + /* Force TIFFAppendToStrip() to consider placing data at end of file. */ tif->tif_curoff = 0; } - /* - * Compute tiles per row & per column to compute - * current row and column - */ - tif->tif_row = (tile % TIFFhowmany_32(td->td_imagelength, td->td_tilelength)) - * td->td_tilelength; - tif->tif_col = (tile % TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth)) - * td->td_tilewidth; + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; - if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { - if (!(*tif->tif_setupencode)(tif)) - return ((tmsize_t)(-1)); - tif->tif_flags |= TIFF_CODERSETUP; + /* + * Compute tiles per row & per column to compute + * current row and column + */ + howmany32=TIFFhowmany_32(td->td_imagelength, td->td_tilelength); + if (howmany32 == 0) { + TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles"); + return ((tmsize_t)(-1)); + } + tif->tif_row = (tile % howmany32) * td->td_tilelength; + howmany32=TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth); + if (howmany32 == 0) { + TIFFErrorExt(tif->tif_clientdata,module,"Zero tiles"); + return ((tmsize_t)(-1)); + } + tif->tif_col = (tile % howmany32) * td->td_tilewidth; + + if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { + if (!(*tif->tif_setupencode)(tif)) + return ((tmsize_t)(-1)); + tif->tif_flags |= TIFF_CODERSETUP; + } + tif->tif_flags &= ~TIFF_POSTENCODE; + + /* + * Clamp write amount to the tile size. This is mostly + * done so that callers can pass in some large number + * (e.g. -1) and have the tile size used instead. + */ + if ( cc < 1 || cc > tif->tif_tilesize) + cc = tif->tif_tilesize; + + /* shortcut to avoid an extra memcpy() */ + if( td->td_compression == COMPRESSION_NONE ) + { + /* swab if needed - note that source buffer will be altered */ + tif->tif_postdecode( tif, (uint8*) data, cc ); + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits((uint8*) data, cc); + + if (cc > 0 && + !TIFFAppendToStrip(tif, tile, (uint8*) data, cc)) + return ((tmsize_t) -1); + return (cc); } - tif->tif_flags &= ~TIFF_POSTENCODE; + sample = (uint16)(tile/td->td_stripsperimage); if (!(*tif->tif_preencode)(tif, sample)) return ((tmsize_t)(-1)); - /* - * Clamp write amount to the tile size. This is mostly - * done so that callers can pass in some large number - * (e.g. -1) and have the tile size used instead. - */ - if ( cc < 1 || cc > tif->tif_tilesize) - cc = tif->tif_tilesize; - - /* swab if needed - note that source buffer will be altered */ + /* swab if needed - note that source buffer will be altered */ tif->tif_postdecode( tif, (uint8*) data, cc ); if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample)) - return (0); + return ((tmsize_t) -1); if (!(*tif->tif_postencode)(tif)) - return ((tmsize_t)(-1)); + return ((tmsize_t)(-1)); if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) - TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc); + TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc); if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile, tif->tif_rawdata, tif->tif_rawcc)) - return ((tmsize_t)(-1)); + return ((tmsize_t)(-1)); tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; return (cc); @@ -428,18 +506,18 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) tmsize_t TIFFWriteRawTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) { - static const char module[] = "TIFFWriteRawTile"; + static const char module[] = "TIFFWriteRawTile"; - if (!WRITECHECKTILES(tif, module)) - return ((tmsize_t)(-1)); - if (tile >= tif->tif_dir.td_nstrips) { - TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu", - (unsigned long) tile, - (unsigned long) tif->tif_dir.td_nstrips); - return ((tmsize_t)(-1)); - } - return (TIFFAppendToStrip(tif, tile, (uint8*) data, cc) ? - cc : (tmsize_t)(-1)); + if (!WRITECHECKTILES(tif, module)) + return ((tmsize_t)(-1)); + if (tile >= tif->tif_dir.td_nstrips) { + TIFFErrorExt(tif->tif_clientdata, module, "Tile %lu out of range, max %lu", + (unsigned long) tile, + (unsigned long) tif->tif_dir.td_nstrips); + return ((tmsize_t)(-1)); + } + return (TIFFAppendToStrip(tif, tile, (uint8*) data, cc) ? + cc : (tmsize_t)(-1)); } #define isUnspecified(tif, f) \ @@ -448,34 +526,34 @@ TIFFWriteRawTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) int TIFFSetupStrips(TIFF* tif) { - TIFFDirectory* td = &tif->tif_dir; + TIFFDirectory* td = &tif->tif_dir; - if (isTiled(tif)) - td->td_stripsperimage = - isUnspecified(tif, FIELD_TILEDIMENSIONS) ? - td->td_samplesperpixel : TIFFNumberOfTiles(tif); - else - td->td_stripsperimage = - isUnspecified(tif, FIELD_ROWSPERSTRIP) ? - td->td_samplesperpixel : TIFFNumberOfStrips(tif); - td->td_nstrips = td->td_stripsperimage; - if (td->td_planarconfig == PLANARCONFIG_SEPARATE) - td->td_stripsperimage /= td->td_samplesperpixel; - td->td_stripoffset = (uint64 *) - _TIFFmalloc(td->td_nstrips * sizeof (uint64)); - td->td_stripbytecount = (uint64 *) - _TIFFmalloc(td->td_nstrips * sizeof (uint64)); - if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) - return (0); - /* - * Place data at the end-of-file - * (by setting offsets to zero). - */ - _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64)); - _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64)); - TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); - TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); - return (1); + if (isTiled(tif)) + td->td_stripsperimage = + isUnspecified(tif, FIELD_TILEDIMENSIONS) ? + td->td_samplesperpixel : TIFFNumberOfTiles(tif); + else + td->td_stripsperimage = + isUnspecified(tif, FIELD_ROWSPERSTRIP) ? + td->td_samplesperpixel : TIFFNumberOfStrips(tif); + td->td_nstrips = td->td_stripsperimage; + if (td->td_planarconfig == PLANARCONFIG_SEPARATE) + td->td_stripsperimage /= td->td_samplesperpixel; + td->td_stripoffset = (uint64 *) + _TIFFmalloc(td->td_nstrips * sizeof (uint64)); + td->td_stripbytecount = (uint64 *) + _TIFFmalloc(td->td_nstrips * sizeof (uint64)); + if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) + return (0); + /* + * Place data at the end-of-file + * (by setting offsets to zero). + */ + _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64)); + _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64)); + TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); + TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); + return (1); } #undef isUnspecified @@ -488,69 +566,69 @@ TIFFSetupStrips(TIFF* tif) int TIFFWriteCheck(TIFF* tif, int tiles, const char* module) { - if (tif->tif_mode == O_RDONLY) { - TIFFErrorExt(tif->tif_clientdata, module, "File not open for writing"); - return (0); - } - if (tiles ^ isTiled(tif)) { - TIFFErrorExt(tif->tif_clientdata, module, tiles ? - "Can not write tiles to a stripped image" : - "Can not write scanlines to a tiled image"); - return (0); - } + if (tif->tif_mode == O_RDONLY) { + TIFFErrorExt(tif->tif_clientdata, module, "File not open for writing"); + return (0); + } + if (tiles ^ isTiled(tif)) { + TIFFErrorExt(tif->tif_clientdata, module, tiles ? + "Can not write tiles to a stripped image" : + "Can not write scanlines to a tiled image"); + return (0); + } _TIFFFillStriles( tif ); - - /* - * On the first write verify all the required information - * has been setup and initialize any data structures that - * had to wait until directory information was set. - * Note that a lot of our work is assumed to remain valid - * because we disallow any of the important parameters - * from changing after we start writing (i.e. once - * TIFF_BEENWRITING is set, TIFFSetField will only allow - * the image's length to be changed). - */ - if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Must set \"ImageWidth\" before writing data"); - return (0); - } - if (tif->tif_dir.td_samplesperpixel == 1) { - /* - * Planarconfiguration is irrelevant in case of single band - * images and need not be included. We will set it anyway, - * because this field is used in other parts of library even - * in the single band case. - */ - if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) + + /* + * On the first write verify all the required information + * has been setup and initialize any data structures that + * had to wait until directory information was set. + * Note that a lot of our work is assumed to remain valid + * because we disallow any of the important parameters + * from changing after we start writing (i.e. once + * TIFF_BEENWRITING is set, TIFFSetField will only allow + * the image's length to be changed). + */ + if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Must set \"ImageWidth\" before writing data"); + return (0); + } + if (tif->tif_dir.td_samplesperpixel == 1) { + /* + * Planarconfiguration is irrelevant in case of single band + * images and need not be included. We will set it anyway, + * because this field is used in other parts of library even + * in the single band case. + */ + if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG; - } else { - if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { - TIFFErrorExt(tif->tif_clientdata, module, - "Must set \"PlanarConfiguration\" before writing data"); - return (0); - } - } - if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { - tif->tif_dir.td_nstrips = 0; - TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays", - isTiled(tif) ? "tile" : "strip"); - return (0); - } - if (isTiled(tif)) - { - tif->tif_tilesize = TIFFTileSize(tif); - if (tif->tif_tilesize == 0) - return (0); - } - else - tif->tif_tilesize = (tmsize_t)(-1); - tif->tif_scanlinesize = TIFFScanlineSize(tif); - if (tif->tif_scanlinesize == 0) - return (0); - tif->tif_flags |= TIFF_BEENWRITING; - return (1); + } else { + if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { + TIFFErrorExt(tif->tif_clientdata, module, + "Must set \"PlanarConfiguration\" before writing data"); + return (0); + } + } + if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { + tif->tif_dir.td_nstrips = 0; + TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays", + isTiled(tif) ? "tile" : "strip"); + return (0); + } + if (isTiled(tif)) + { + tif->tif_tilesize = TIFFTileSize(tif); + if (tif->tif_tilesize == 0) + return (0); + } + else + tif->tif_tilesize = (tmsize_t)(-1); + tif->tif_scanlinesize = TIFFScanlineSize(tif); + if (tif->tif_scanlinesize == 0) + return (0); + tif->tif_flags |= TIFF_BEENWRITING; + return (1); } /* @@ -559,40 +637,40 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module) int TIFFWriteBufferSetup(TIFF* tif, void* bp, tmsize_t size) { - static const char module[] = "TIFFWriteBufferSetup"; + static const char module[] = "TIFFWriteBufferSetup"; - if (tif->tif_rawdata) { - if (tif->tif_flags & TIFF_MYBUFFER) { - _TIFFfree(tif->tif_rawdata); - tif->tif_flags &= ~TIFF_MYBUFFER; - } - tif->tif_rawdata = NULL; - } - if (size == (tmsize_t)(-1)) { - size = (isTiled(tif) ? - tif->tif_tilesize : TIFFStripSize(tif)); - /* - * Make raw data buffer at least 8K - */ - if (size < 8*1024) - size = 8*1024; - bp = NULL; /* NB: force malloc */ - } - if (bp == NULL) { - bp = _TIFFmalloc(size); - if (bp == NULL) { - TIFFErrorExt(tif->tif_clientdata, module, "No space for output buffer"); - return (0); - } - tif->tif_flags |= TIFF_MYBUFFER; - } else - tif->tif_flags &= ~TIFF_MYBUFFER; - tif->tif_rawdata = (uint8*) bp; - tif->tif_rawdatasize = size; - tif->tif_rawcc = 0; - tif->tif_rawcp = tif->tif_rawdata; - tif->tif_flags |= TIFF_BUFFERSETUP; - return (1); + if (tif->tif_rawdata) { + if (tif->tif_flags & TIFF_MYBUFFER) { + _TIFFfree(tif->tif_rawdata); + tif->tif_flags &= ~TIFF_MYBUFFER; + } + tif->tif_rawdata = NULL; + } + if (size == (tmsize_t)(-1)) { + size = (isTiled(tif) ? + tif->tif_tilesize : TIFFStripSize(tif)); + /* + * Make raw data buffer at least 8K + */ + if (size < 8*1024) + size = 8*1024; + bp = NULL; /* NB: force malloc */ + } + if (bp == NULL) { + bp = _TIFFmalloc(size); + if (bp == NULL) { + TIFFErrorExt(tif->tif_clientdata, module, "No space for output buffer"); + return (0); + } + tif->tif_flags |= TIFF_MYBUFFER; + } else + tif->tif_flags &= ~TIFF_MYBUFFER; + tif->tif_rawdata = (uint8*) bp; + tif->tif_rawdatasize = size; + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + tif->tif_flags |= TIFF_BUFFERSETUP; + return (1); } /* @@ -601,34 +679,34 @@ TIFFWriteBufferSetup(TIFF* tif, void* bp, tmsize_t size) static int TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module) { - TIFFDirectory *td = &tif->tif_dir; - uint64* new_stripoffset; - uint64* new_stripbytecount; + TIFFDirectory *td = &tif->tif_dir; + uint64* new_stripoffset; + uint64* new_stripbytecount; - assert(td->td_planarconfig == PLANARCONFIG_CONTIG); - new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset, - (td->td_nstrips + delta) * sizeof (uint64)); - new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount, - (td->td_nstrips + delta) * sizeof (uint64)); - if (new_stripoffset == NULL || new_stripbytecount == NULL) { - if (new_stripoffset) - _TIFFfree(new_stripoffset); - if (new_stripbytecount) - _TIFFfree(new_stripbytecount); - td->td_nstrips = 0; - TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays"); - return (0); - } - td->td_stripoffset = new_stripoffset; - td->td_stripbytecount = new_stripbytecount; - _TIFFmemset(td->td_stripoffset + td->td_nstrips, - 0, delta*sizeof (uint64)); - _TIFFmemset(td->td_stripbytecount + td->td_nstrips, - 0, delta*sizeof (uint64)); - td->td_nstrips += delta; + assert(td->td_planarconfig == PLANARCONFIG_CONTIG); + new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset, + (td->td_nstrips + delta) * sizeof (uint64)); + new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount, + (td->td_nstrips + delta) * sizeof (uint64)); + if (new_stripoffset == NULL || new_stripbytecount == NULL) { + if (new_stripoffset) + _TIFFfree(new_stripoffset); + if (new_stripbytecount) + _TIFFfree(new_stripbytecount); + td->td_nstrips = 0; + TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays"); + return (0); + } + td->td_stripoffset = new_stripoffset; + td->td_stripbytecount = new_stripbytecount; + _TIFFmemset(td->td_stripoffset + td->td_nstrips, + 0, delta*sizeof (uint64)); + _TIFFmemset(td->td_stripbytecount + td->td_nstrips, + 0, delta*sizeof (uint64)); + td->td_nstrips += delta; tif->tif_flags |= TIFF_DIRTYDIRECT; - return (1); + return (1); } /* @@ -637,21 +715,21 @@ TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module) static int TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc) { - static const char module[] = "TIFFAppendToStrip"; - TIFFDirectory *td = &tif->tif_dir; - uint64 m; + static const char module[] = "TIFFAppendToStrip"; + TIFFDirectory *td = &tif->tif_dir; + uint64 m; int64 old_byte_count = -1; - if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { + if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { assert(td->td_nstrips > 0); - if( td->td_stripbytecount[strip] != 0 - && td->td_stripoffset[strip] != 0 + if( td->td_stripbytecount[strip] != 0 + && td->td_stripoffset[strip] != 0 && td->td_stripbytecount[strip] >= (uint64) cc ) { - /* + /* * There is already tile data on disk, and the new tile - * data we have will fit in the same space. The only + * data we have will fit in the same space. The only * aspect of this that is risky is that there could be * more data to append to this strip before we are done * depending on how we are getting called. @@ -665,8 +743,8 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc) } else { - /* - * Seek to end of file, and set that as our location to + /* + * Seek to end of file, and set that as our location to * write this strip. */ td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END); @@ -680,28 +758,28 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc) */ old_byte_count = td->td_stripbytecount[strip]; td->td_stripbytecount[strip] = 0; - } + } - m = tif->tif_curoff+cc; - if (!(tif->tif_flags&TIFF_BIGTIFF)) - m = (uint32)m; - if ((mtif_curoff)||(m<(uint64)cc)) - { - TIFFErrorExt(tif->tif_clientdata, module, "Maximum TIFF file size exceeded"); - return (0); - } - if (!WriteOK(tif, data, cc)) { - TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu", - (unsigned long) tif->tif_row); - return (0); - } - tif->tif_curoff = m; - td->td_stripbytecount[strip] += cc; + m = tif->tif_curoff+cc; + if (!(tif->tif_flags&TIFF_BIGTIFF)) + m = (uint32)m; + if ((mtif_curoff)||(m<(uint64)cc)) + { + TIFFErrorExt(tif->tif_clientdata, module, "Maximum TIFF file size exceeded"); + return (0); + } + if (!WriteOK(tif, data, cc)) { + TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu", + (unsigned long) tif->tif_row); + return (0); + } + tif->tif_curoff = m; + td->td_stripbytecount[strip] += cc; if( (int64) td->td_stripbytecount[strip] != old_byte_count ) tif->tif_flags |= TIFF_DIRTYSTRIP; - - return (1); + + return (1); } /* @@ -712,19 +790,26 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc) int TIFFFlushData1(TIFF* tif) { - if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE ) { - if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && - (tif->tif_flags & TIFF_NOBITREV) == 0) - TIFFReverseBits((uint8*)tif->tif_rawdata, - tif->tif_rawcc); - if (!TIFFAppendToStrip(tif, - isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, - tif->tif_rawdata, tif->tif_rawcc)) - return (0); - tif->tif_rawcc = 0; - tif->tif_rawcp = tif->tif_rawdata; - } - return (1); + if (tif->tif_rawcc > 0 && tif->tif_flags & TIFF_BUF4WRITE ) { + if (!isFillOrder(tif, tif->tif_dir.td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + TIFFReverseBits((uint8*)tif->tif_rawdata, + tif->tif_rawcc); + if (!TIFFAppendToStrip(tif, + isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, + tif->tif_rawdata, tif->tif_rawcc)) + { + /* We update those variables even in case of error since there's */ + /* code that doesn't really check the return code of this */ + /* function */ + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + return (0); + } + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + } + return (1); } /* @@ -736,7 +821,7 @@ TIFFFlushData1(TIFF* tif) void TIFFSetWriteOffset(TIFF* tif, toff_t off) { - tif->tif_curoff = off; + tif->tif_curoff = off; } /* vim: set ts=8 sts=8 sw=8 noet: */ diff --git a/3rdparty/libtiff/tif_zip.c b/3rdparty/libtiff/tif_zip.c index 4275a7fd29..42943fbb14 100644 --- a/3rdparty/libtiff/tif_zip.c +++ b/3rdparty/libtiff/tif_zip.c @@ -1,26 +1,26 @@ -/* $Id: tif_zip.c,v 1.31 2011-01-06 16:00:23 fwarmerdam Exp $ */ +/* $Id: tif_zip.c,v 1.37 2017-05-10 15:21:16 erouault Exp $ */ /* * Copyright (c) 1995-1997 Sam Leffler * Copyright (c) 1995-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -36,7 +36,7 @@ * of the library: this code assumes the 1.0 API and also depends on * the ability to write the zlib header multiple times (one per strip) * which was not possible with versions prior to 0.95. Note also that - * older versions of this codec avoided this bug by supressing the header + * older versions of this codec avoided this bug by suppressing the header * entirely. This means that files written with the old library cannot * be read; they should be converted to a different compression scheme * and then reconverted. @@ -61,20 +61,22 @@ #error "Antiquated ZLIB software; you must use version 1.0 or later" #endif +#define SAFE_MSG(sp) ((sp)->stream.msg == NULL ? "" : (sp)->stream.msg) + /* * State block for each open TIFF * file using ZIP compression/decompression. */ typedef struct { - TIFFPredictorState predict; + TIFFPredictorState predict; z_stream stream; - int zipquality; /* compression level */ - int state; /* state flags */ + int zipquality; /* compression level */ + int state; /* state flags */ #define ZSTATE_INIT_DECODE 0x01 #define ZSTATE_INIT_ENCODE 0x02 - TIFFVGetMethod vgetparent; /* super-class method */ - TIFFVSetMethod vsetparent; /* super-class method */ + TIFFVGetMethod vgetparent; /* super-class method */ + TIFFVSetMethod vsetparent; /* super-class method */ } ZIPState; #define ZState(tif) ((ZIPState*) (tif)->tif_data) @@ -87,31 +89,35 @@ static int ZIPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s); static int ZIPFixupTags(TIFF* tif) { - (void) tif; - return (1); + (void) tif; + return (1); } static int ZIPSetupDecode(TIFF* tif) { - static const char module[] = "ZIPSetupDecode"; - ZIPState* sp = DecoderState(tif); - - assert(sp != NULL); + static const char module[] = "ZIPSetupDecode"; + ZIPState* sp = DecoderState(tif); + assert(sp != NULL); + /* if we were last encoding, terminate this mode */ - if (sp->state & ZSTATE_INIT_ENCODE) { - deflateEnd(&sp->stream); - sp->state = 0; - } + if (sp->state & ZSTATE_INIT_ENCODE) { + deflateEnd(&sp->stream); + sp->state = 0; + } - if (inflateInit(&sp->stream) != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg); - return (0); - } else { - sp->state |= ZSTATE_INIT_DECODE; - return (1); - } + /* This function can possibly be called several times by */ + /* PredictorSetupDecode() if this function succeeds but */ + /* PredictorSetup() fails */ + if ((sp->state & ZSTATE_INIT_DECODE) == 0 && + inflateInit(&sp->stream) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s", SAFE_MSG(sp)); + return (0); + } else { + sp->state |= ZSTATE_INIT_DECODE; + return (1); + } } /* @@ -120,103 +126,103 @@ ZIPSetupDecode(TIFF* tif) static int ZIPPreDecode(TIFF* tif, uint16 s) { - static const char module[] = "ZIPPreDecode"; - ZIPState* sp = DecoderState(tif); + static const char module[] = "ZIPPreDecode"; + ZIPState* sp = DecoderState(tif); - (void) s; - assert(sp != NULL); + (void) s; + assert(sp != NULL); - if( (sp->state & ZSTATE_INIT_DECODE) == 0 ) + if( (sp->state & ZSTATE_INIT_DECODE) == 0 ) tif->tif_setupdecode( tif ); - sp->stream.next_in = tif->tif_rawdata; - assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, - we need to simplify this code to reflect a ZLib that is likely updated - to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ - sp->stream.avail_in = (uInt) tif->tif_rawcc; - if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) - { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } - return (inflateReset(&sp->stream) == Z_OK); + sp->stream.next_in = tif->tif_rawdata; + assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, + we need to simplify this code to reflect a ZLib that is likely updated + to deal with 8byte memory sizes, though this code will respond + appropriately even before we simplify it */ + sp->stream.avail_in = (uInt) tif->tif_rawcc; + if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) + { + TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); + return (0); + } + return (inflateReset(&sp->stream) == Z_OK); } static int ZIPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) { - static const char module[] = "ZIPDecode"; - ZIPState* sp = DecoderState(tif); + static const char module[] = "ZIPDecode"; + ZIPState* sp = DecoderState(tif); - (void) s; - assert(sp != NULL); - assert(sp->state == ZSTATE_INIT_DECODE); + (void) s; + assert(sp != NULL); + assert(sp->state == ZSTATE_INIT_DECODE); sp->stream.next_in = tif->tif_rawcp; - sp->stream.avail_in = (uInt) tif->tif_rawcc; - - sp->stream.next_out = op; - assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, - we need to simplify this code to reflect a ZLib that is likely updated - to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ - sp->stream.avail_out = (uInt) occ; - if ((tmsize_t)sp->stream.avail_out != occ) - { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } - do { - int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); - if (state == Z_STREAM_END) - break; - if (state == Z_DATA_ERROR) { - TIFFErrorExt(tif->tif_clientdata, module, - "Decoding error at scanline %lu, %s", - (unsigned long) tif->tif_row, sp->stream.msg); - if (inflateSync(&sp->stream) != Z_OK) - return (0); - continue; - } - if (state != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", - sp->stream.msg); - return (0); - } - } while (sp->stream.avail_out > 0); - if (sp->stream.avail_out != 0) { - TIFFErrorExt(tif->tif_clientdata, module, - "Not enough data at scanline %lu (short " TIFF_UINT64_FORMAT " bytes)", - (unsigned long) tif->tif_row, (TIFF_UINT64_T) sp->stream.avail_out); - return (0); - } + sp->stream.avail_in = (uInt) tif->tif_rawcc; + + sp->stream.next_out = op; + assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, + we need to simplify this code to reflect a ZLib that is likely updated + to deal with 8byte memory sizes, though this code will respond + appropriately even before we simplify it */ + sp->stream.avail_out = (uInt) occ; + if ((tmsize_t)sp->stream.avail_out != occ) + { + TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); + return (0); + } + do { + int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); + if (state == Z_STREAM_END) + break; + if (state == Z_DATA_ERROR) { + TIFFErrorExt(tif->tif_clientdata, module, + "Decoding error at scanline %lu, %s", + (unsigned long) tif->tif_row, SAFE_MSG(sp)); + if (inflateSync(&sp->stream) != Z_OK) + return (0); + continue; + } + if (state != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, + "ZLib error: %s", SAFE_MSG(sp)); + return (0); + } + } while (sp->stream.avail_out > 0); + if (sp->stream.avail_out != 0) { + TIFFErrorExt(tif->tif_clientdata, module, + "Not enough data at scanline %lu (short " TIFF_UINT64_FORMAT " bytes)", + (unsigned long) tif->tif_row, (TIFF_UINT64_T) sp->stream.avail_out); + return (0); + } tif->tif_rawcp = sp->stream.next_in; tif->tif_rawcc = sp->stream.avail_in; - return (1); + return (1); } static int ZIPSetupEncode(TIFF* tif) { - static const char module[] = "ZIPSetupEncode"; - ZIPState* sp = EncoderState(tif); + static const char module[] = "ZIPSetupEncode"; + ZIPState* sp = EncoderState(tif); - assert(sp != NULL); - if (sp->state & ZSTATE_INIT_DECODE) { - inflateEnd(&sp->stream); - sp->state = 0; - } + assert(sp != NULL); + if (sp->state & ZSTATE_INIT_DECODE) { + inflateEnd(&sp->stream); + sp->state = 0; + } - if (deflateInit(&sp->stream, sp->zipquality) != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg); - return (0); - } else { - sp->state |= ZSTATE_INIT_ENCODE; - return (1); - } + if (deflateInit(&sp->stream, sp->zipquality) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "%s", SAFE_MSG(sp)); + return (0); + } else { + sp->state |= ZSTATE_INIT_ENCODE; + return (1); + } } /* @@ -225,26 +231,26 @@ ZIPSetupEncode(TIFF* tif) static int ZIPPreEncode(TIFF* tif, uint16 s) { - static const char module[] = "ZIPPreEncode"; - ZIPState *sp = EncoderState(tif); + static const char module[] = "ZIPPreEncode"; + ZIPState *sp = EncoderState(tif); - (void) s; - assert(sp != NULL); - if( sp->state != ZSTATE_INIT_ENCODE ) + (void) s; + assert(sp != NULL); + if( sp->state != ZSTATE_INIT_ENCODE ) tif->tif_setupencode( tif ); - sp->stream.next_out = tif->tif_rawdata; - assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, - we need to simplify this code to reflect a ZLib that is likely updated - to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ - sp->stream.avail_out = tif->tif_rawdatasize; - if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) - { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } - return (deflateReset(&sp->stream) == Z_OK); + sp->stream.next_out = tif->tif_rawdata; + assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, + we need to simplify this code to reflect a ZLib that is likely updated + to deal with 8byte memory sizes, though this code will respond + appropriately even before we simplify it */ + sp->stream.avail_out = (uInt)tif->tif_rawdatasize; + if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) + { + TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); + return (0); + } + return (deflateReset(&sp->stream) == Z_OK); } /* @@ -253,38 +259,39 @@ ZIPPreEncode(TIFF* tif, uint16 s) static int ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) { - static const char module[] = "ZIPEncode"; - ZIPState *sp = EncoderState(tif); + static const char module[] = "ZIPEncode"; + ZIPState *sp = EncoderState(tif); - assert(sp != NULL); - assert(sp->state == ZSTATE_INIT_ENCODE); + assert(sp != NULL); + assert(sp->state == ZSTATE_INIT_ENCODE); - (void) s; - sp->stream.next_in = bp; - assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, - we need to simplify this code to reflect a ZLib that is likely updated - to deal with 8byte memory sizes, though this code will respond - apropriately even before we simplify it */ - sp->stream.avail_in = (uInt) cc; - if ((tmsize_t)sp->stream.avail_in != cc) - { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } - do { - if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "Encoder error: %s", - sp->stream.msg); - return (0); - } - if (sp->stream.avail_out == 0) { - tif->tif_rawcc = tif->tif_rawdatasize; - TIFFFlushData1(tif); - sp->stream.next_out = tif->tif_rawdata; - sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in ZIPPreEncode */ - } - } while (sp->stream.avail_in > 0); - return (1); + (void) s; + sp->stream.next_in = bp; + assert(sizeof(sp->stream.avail_in)==4); /* if this assert gets raised, + we need to simplify this code to reflect a ZLib that is likely updated + to deal with 8byte memory sizes, though this code will respond + appropriately even before we simplify it */ + sp->stream.avail_in = (uInt) cc; + if ((tmsize_t)sp->stream.avail_in != cc) + { + TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); + return (0); + } + do { + if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, + "Encoder error: %s", + SAFE_MSG(sp)); + return (0); + } + if (sp->stream.avail_out == 0) { + tif->tif_rawcc = tif->tif_rawdatasize; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in ZIPPreEncode */ + } + } while (sp->stream.avail_in > 0); + return (1); } /* @@ -294,95 +301,95 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) static int ZIPPostEncode(TIFF* tif) { - static const char module[] = "ZIPPostEncode"; - ZIPState *sp = EncoderState(tif); - int state; + static const char module[] = "ZIPPostEncode"; + ZIPState *sp = EncoderState(tif); + int state; - sp->stream.avail_in = 0; - do { - state = deflate(&sp->stream, Z_FINISH); - switch (state) { - case Z_STREAM_END: - case Z_OK: - if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) - { - tif->tif_rawcc = tif->tif_rawdatasize - sp->stream.avail_out; - TIFFFlushData1(tif); - sp->stream.next_out = tif->tif_rawdata; - sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in ZIPPreEncode */ - } - break; - default: - TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", - sp->stream.msg); - return (0); - } - } while (state != Z_STREAM_END); - return (1); + sp->stream.avail_in = 0; + do { + state = deflate(&sp->stream, Z_FINISH); + switch (state) { + case Z_STREAM_END: + case Z_OK: + if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) + { + tif->tif_rawcc = tif->tif_rawdatasize - sp->stream.avail_out; + TIFFFlushData1(tif); + sp->stream.next_out = tif->tif_rawdata; + sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in ZIPPreEncode */ + } + break; + default: + TIFFErrorExt(tif->tif_clientdata, module, + "ZLib error: %s", SAFE_MSG(sp)); + return (0); + } + } while (state != Z_STREAM_END); + return (1); } static void ZIPCleanup(TIFF* tif) { - ZIPState* sp = ZState(tif); + ZIPState* sp = ZState(tif); - assert(sp != 0); + assert(sp != 0); - (void)TIFFPredictorCleanup(tif); + (void)TIFFPredictorCleanup(tif); - tif->tif_tagmethods.vgetfield = sp->vgetparent; - tif->tif_tagmethods.vsetfield = sp->vsetparent; + tif->tif_tagmethods.vgetfield = sp->vgetparent; + tif->tif_tagmethods.vsetfield = sp->vsetparent; - if (sp->state & ZSTATE_INIT_ENCODE) { - deflateEnd(&sp->stream); - sp->state = 0; - } else if( sp->state & ZSTATE_INIT_DECODE) { - inflateEnd(&sp->stream); - sp->state = 0; - } - _TIFFfree(sp); - tif->tif_data = NULL; + if (sp->state & ZSTATE_INIT_ENCODE) { + deflateEnd(&sp->stream); + sp->state = 0; + } else if( sp->state & ZSTATE_INIT_DECODE) { + inflateEnd(&sp->stream); + sp->state = 0; + } + _TIFFfree(sp); + tif->tif_data = NULL; - _TIFFSetDefaultCompressionState(tif); + _TIFFSetDefaultCompressionState(tif); } static int ZIPVSetField(TIFF* tif, uint32 tag, va_list ap) { - static const char module[] = "ZIPVSetField"; - ZIPState* sp = ZState(tif); + static const char module[] = "ZIPVSetField"; + ZIPState* sp = ZState(tif); - switch (tag) { - case TIFFTAG_ZIPQUALITY: - sp->zipquality = (int) va_arg(ap, int); - if ( sp->state&ZSTATE_INIT_ENCODE ) { - if (deflateParams(&sp->stream, - sp->zipquality, Z_DEFAULT_STRATEGY) != Z_OK) { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", - sp->stream.msg); - return (0); - } - } - return (1); - default: - return (*sp->vsetparent)(tif, tag, ap); - } - /*NOTREACHED*/ + switch (tag) { + case TIFFTAG_ZIPQUALITY: + sp->zipquality = (int) va_arg(ap, int); + if ( sp->state&ZSTATE_INIT_ENCODE ) { + if (deflateParams(&sp->stream, + sp->zipquality, Z_DEFAULT_STRATEGY) != Z_OK) { + TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", + SAFE_MSG(sp)); + return (0); + } + } + return (1); + default: + return (*sp->vsetparent)(tif, tag, ap); + } + /*NOTREACHED*/ } static int ZIPVGetField(TIFF* tif, uint32 tag, va_list ap) { - ZIPState* sp = ZState(tif); + ZIPState* sp = ZState(tif); - switch (tag) { - case TIFFTAG_ZIPQUALITY: - *va_arg(ap, int*) = sp->zipquality; - break; - default: - return (*sp->vgetparent)(tif, tag, ap); - } - return (1); + switch (tag) { + case TIFFTAG_ZIPQUALITY: + *va_arg(ap, int*) = sp->zipquality; + break; + default: + return (*sp->vgetparent)(tif, tag, ap); + } + return (1); } static const TIFFField zipFields[] = { @@ -392,72 +399,72 @@ static const TIFFField zipFields[] = { int TIFFInitZIP(TIFF* tif, int scheme) { - static const char module[] = "TIFFInitZIP"; - ZIPState* sp; + static const char module[] = "TIFFInitZIP"; + ZIPState* sp; - assert( (scheme == COMPRESSION_DEFLATE) - || (scheme == COMPRESSION_ADOBE_DEFLATE)); + assert( (scheme == COMPRESSION_DEFLATE) + || (scheme == COMPRESSION_ADOBE_DEFLATE)); - /* - * Merge codec-specific tag information. - */ - if (!_TIFFMergeFields(tif, zipFields, TIFFArrayCount(zipFields))) { - TIFFErrorExt(tif->tif_clientdata, module, - "Merging Deflate codec-specific tags failed"); - return 0; - } + /* + * Merge codec-specific tag information. + */ + if (!_TIFFMergeFields(tif, zipFields, TIFFArrayCount(zipFields))) { + TIFFErrorExt(tif->tif_clientdata, module, + "Merging Deflate codec-specific tags failed"); + return 0; + } - /* - * Allocate state block so tag methods have storage to record values. - */ - tif->tif_data = (uint8*) _TIFFmalloc(sizeof (ZIPState)); - if (tif->tif_data == NULL) - goto bad; - sp = ZState(tif); - sp->stream.zalloc = NULL; - sp->stream.zfree = NULL; - sp->stream.opaque = NULL; - sp->stream.data_type = Z_BINARY; + /* + * Allocate state block so tag methods have storage to record values. + */ + tif->tif_data = (uint8*) _TIFFmalloc(sizeof (ZIPState)); + if (tif->tif_data == NULL) + goto bad; + sp = ZState(tif); + sp->stream.zalloc = NULL; + sp->stream.zfree = NULL; + sp->stream.opaque = NULL; + sp->stream.data_type = Z_BINARY; - /* - * Override parent get/set field methods. - */ - sp->vgetparent = tif->tif_tagmethods.vgetfield; - tif->tif_tagmethods.vgetfield = ZIPVGetField; /* hook for codec tags */ - sp->vsetparent = tif->tif_tagmethods.vsetfield; - tif->tif_tagmethods.vsetfield = ZIPVSetField; /* hook for codec tags */ + /* + * Override parent get/set field methods. + */ + sp->vgetparent = tif->tif_tagmethods.vgetfield; + tif->tif_tagmethods.vgetfield = ZIPVGetField; /* hook for codec tags */ + sp->vsetparent = tif->tif_tagmethods.vsetfield; + tif->tif_tagmethods.vsetfield = ZIPVSetField; /* hook for codec tags */ - /* Default values for codec-specific fields */ - sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */ - sp->state = 0; + /* Default values for codec-specific fields */ + sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */ + sp->state = 0; - /* - * Install codec methods. - */ - tif->tif_fixuptags = ZIPFixupTags; - tif->tif_setupdecode = ZIPSetupDecode; - tif->tif_predecode = ZIPPreDecode; - tif->tif_decoderow = ZIPDecode; - tif->tif_decodestrip = ZIPDecode; - tif->tif_decodetile = ZIPDecode; - tif->tif_setupencode = ZIPSetupEncode; - tif->tif_preencode = ZIPPreEncode; - tif->tif_postencode = ZIPPostEncode; - tif->tif_encoderow = ZIPEncode; - tif->tif_encodestrip = ZIPEncode; - tif->tif_encodetile = ZIPEncode; - tif->tif_cleanup = ZIPCleanup; - /* - * Setup predictor setup. - */ - (void) TIFFPredictorInit(tif); - return (1); + /* + * Install codec methods. + */ + tif->tif_fixuptags = ZIPFixupTags; + tif->tif_setupdecode = ZIPSetupDecode; + tif->tif_predecode = ZIPPreDecode; + tif->tif_decoderow = ZIPDecode; + tif->tif_decodestrip = ZIPDecode; + tif->tif_decodetile = ZIPDecode; + tif->tif_setupencode = ZIPSetupEncode; + tif->tif_preencode = ZIPPreEncode; + tif->tif_postencode = ZIPPostEncode; + tif->tif_encoderow = ZIPEncode; + tif->tif_encodestrip = ZIPEncode; + tif->tif_encodetile = ZIPEncode; + tif->tif_cleanup = ZIPCleanup; + /* + * Setup predictor setup. + */ + (void) TIFFPredictorInit(tif); + return (1); bad: - TIFFErrorExt(tif->tif_clientdata, module, - "No space for ZIP state block"); - return (0); + TIFFErrorExt(tif->tif_clientdata, module, + "No space for ZIP state block"); + return (0); } -#endif /* ZIP_SUPORT */ +#endif /* ZIP_SUPPORT */ /* vim: set ts=8 sts=8 sw=8 noet: */ /* diff --git a/3rdparty/libtiff/tiff.h b/3rdparty/libtiff/tiff.h index 0c66a58a8e..fb39634c4b 100644 --- a/3rdparty/libtiff/tiff.h +++ b/3rdparty/libtiff/tiff.h @@ -1,33 +1,33 @@ -/* $Id: tiff.h,v 1.67 2011-01-24 21:06:32 olivier Exp $ */ +/* $Id: tiff.h,v 1.70 2016-01-23 21:20:34 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #ifndef _TIFF_ #define _TIFF_ -#include "tif_config.h" +#include "tiffconf.h" /* * Tag Image File Format (TIFF) @@ -91,20 +91,20 @@ typedef int uint16_vap; * TIFF header. */ typedef struct { - uint16 tiff_magic; /* magic number (defines byte order) */ - uint16 tiff_version; /* TIFF version number */ + uint16 tiff_magic; /* magic number (defines byte order) */ + uint16 tiff_version; /* TIFF version number */ } TIFFHeaderCommon; typedef struct { - uint16 tiff_magic; /* magic number (defines byte order) */ - uint16 tiff_version; /* TIFF version number */ - uint32 tiff_diroff; /* byte offset to first directory */ + uint16 tiff_magic; /* magic number (defines byte order) */ + uint16 tiff_version; /* TIFF version number */ + uint32 tiff_diroff; /* byte offset to first directory */ } TIFFHeaderClassic; typedef struct { - uint16 tiff_magic; /* magic number (defines byte order) */ - uint16 tiff_version; /* TIFF version number */ - uint16 tiff_offsetsize; /* size of offsets, should be 8 */ - uint16 tiff_unused; /* unused word, should be 0 */ - uint64 tiff_diroff; /* byte offset to first directory */ + uint16 tiff_magic; /* magic number (defines byte order) */ + uint16 tiff_version; /* TIFF version number */ + uint16 tiff_offsetsize; /* size of offsets, should be 8 */ + uint16 tiff_unused; /* unused word, should be 0 */ + uint64 tiff_diroff; /* byte offset to first directory */ } TIFFHeaderBig; @@ -123,23 +123,23 @@ typedef struct { * Note: RATIONALs are the ratio of two 32-bit integer values. */ typedef enum { - TIFF_NOTYPE = 0, /* placeholder */ - TIFF_BYTE = 1, /* 8-bit unsigned integer */ - TIFF_ASCII = 2, /* 8-bit bytes w/ last byte null */ - TIFF_SHORT = 3, /* 16-bit unsigned integer */ - TIFF_LONG = 4, /* 32-bit unsigned integer */ - TIFF_RATIONAL = 5, /* 64-bit unsigned fraction */ - TIFF_SBYTE = 6, /* !8-bit signed integer */ - TIFF_UNDEFINED = 7, /* !8-bit untyped data */ - TIFF_SSHORT = 8, /* !16-bit signed integer */ - TIFF_SLONG = 9, /* !32-bit signed integer */ - TIFF_SRATIONAL = 10, /* !64-bit signed fraction */ - TIFF_FLOAT = 11, /* !32-bit IEEE floating point */ - TIFF_DOUBLE = 12, /* !64-bit IEEE floating point */ - TIFF_IFD = 13, /* %32-bit unsigned integer (offset) */ - TIFF_LONG8 = 16, /* BigTIFF 64-bit unsigned integer */ - TIFF_SLONG8 = 17, /* BigTIFF 64-bit signed integer */ - TIFF_IFD8 = 18 /* BigTIFF 64-bit unsigned integer (offset) */ + TIFF_NOTYPE = 0, /* placeholder */ + TIFF_BYTE = 1, /* 8-bit unsigned integer */ + TIFF_ASCII = 2, /* 8-bit bytes w/ last byte null */ + TIFF_SHORT = 3, /* 16-bit unsigned integer */ + TIFF_LONG = 4, /* 32-bit unsigned integer */ + TIFF_RATIONAL = 5, /* 64-bit unsigned fraction */ + TIFF_SBYTE = 6, /* !8-bit signed integer */ + TIFF_UNDEFINED = 7, /* !8-bit untyped data */ + TIFF_SSHORT = 8, /* !16-bit signed integer */ + TIFF_SLONG = 9, /* !32-bit signed integer */ + TIFF_SRATIONAL = 10, /* !64-bit signed fraction */ + TIFF_FLOAT = 11, /* !32-bit IEEE floating point */ + TIFF_DOUBLE = 12, /* !64-bit IEEE floating point */ + TIFF_IFD = 13, /* %32-bit unsigned integer (offset) */ + TIFF_LONG8 = 16, /* BigTIFF 64-bit unsigned integer */ + TIFF_SLONG8 = 17, /* BigTIFF 64-bit signed integer */ + TIFF_IFD8 = 18 /* BigTIFF 64-bit unsigned integer (offset) */ } TIFFDataType; /* @@ -166,6 +166,8 @@ typedef enum { #define COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */ #define COMPRESSION_OJPEG 6 /* !6.0 JPEG */ #define COMPRESSION_JPEG 7 /* %JPEG DCT compression */ +#define COMPRESSION_T85 9 /* !TIFF/FX T.85 JBIG compression */ +#define COMPRESSION_T43 10 /* !TIFF/FX T.43 colour by layered JBIG compression */ #define COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */ #define COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */ #define COMPRESSION_PACKBITS 32773 /* Macintosh RLE */ @@ -180,7 +182,7 @@ typedef enum { #define COMPRESSION_PIXARLOG 32909 /* Pixar companded 11bit ZIP */ #define COMPRESSION_DEFLATE 32946 /* Deflate compression */ #define COMPRESSION_ADOBE_DEFLATE 8 /* Deflate compression, - as recognized by Adobe */ + as recognized by Adobe */ /* compression code 32947 is reserved for Oceana Matrix */ #define COMPRESSION_DCS 32947 /* Kodak DCS encoding */ #define COMPRESSION_JBIG 34661 /* ISO JBIG */ @@ -199,6 +201,7 @@ typedef enum { #define PHOTOMETRIC_CIELAB 8 /* !1976 CIE L*a*b* */ #define PHOTOMETRIC_ICCLAB 9 /* ICC L*a*b* [Adobe TIFF Technote 4] */ #define PHOTOMETRIC_ITULAB 10 /* ITU L*a*b* */ +#define PHOTOMETRIC_CFA 32803 /* color filter array */ #define PHOTOMETRIC_LOGL 32844 /* CIE Log2(L) */ #define PHOTOMETRIC_LOGLUV 32845 /* CIE Log2(L) (u',v') */ #define TIFFTAG_THRESHHOLDING 263 /* +thresholding used on data */ @@ -276,7 +279,7 @@ typedef enum { #define PREDICTOR_FLOATINGPOINT 3 /* floating point predictor */ #define TIFFTAG_WHITEPOINT 318 /* image white point */ #define TIFFTAG_PRIMARYCHROMATICITIES 319 /* !primary chromaticities */ -#define TIFFTAG_COLORMAP 320 /* RGB map for pallette image */ +#define TIFFTAG_COLORMAP 320 /* RGB map for palette image */ #define TIFFTAG_HALFTONEHINTS 321 /* !highlight+shadow info */ #define TIFFTAG_TILEWIDTH 322 /* !tile width in pixels */ #define TIFFTAG_TILELENGTH 323 /* !tile height in pixels */ @@ -310,15 +313,39 @@ typedef enum { #define TIFFTAG_SMINSAMPLEVALUE 340 /* !variable MinSampleValue */ #define TIFFTAG_SMAXSAMPLEVALUE 341 /* !variable MaxSampleValue */ #define TIFFTAG_CLIPPATH 343 /* %ClipPath - [Adobe TIFF technote 2] */ + [Adobe TIFF technote 2] */ #define TIFFTAG_XCLIPPATHUNITS 344 /* %XClipPathUnits - [Adobe TIFF technote 2] */ + [Adobe TIFF technote 2] */ #define TIFFTAG_YCLIPPATHUNITS 345 /* %YClipPathUnits - [Adobe TIFF technote 2] */ + [Adobe TIFF technote 2] */ #define TIFFTAG_INDEXED 346 /* %Indexed - [Adobe TIFF Technote 3] */ + [Adobe TIFF Technote 3] */ #define TIFFTAG_JPEGTABLES 347 /* %JPEG table stream */ #define TIFFTAG_OPIPROXY 351 /* %OPI Proxy [Adobe TIFF technote] */ +/* Tags 400-435 are from the TIFF/FX spec */ +#define TIFFTAG_GLOBALPARAMETERSIFD 400 /* ! */ +#define TIFFTAG_PROFILETYPE 401 /* ! */ +#define PROFILETYPE_UNSPECIFIED 0 /* ! */ +#define PROFILETYPE_G3_FAX 1 /* ! */ +#define TIFFTAG_FAXPROFILE 402 /* ! */ +#define FAXPROFILE_S 1 /* !TIFF/FX FAX profile S */ +#define FAXPROFILE_F 2 /* !TIFF/FX FAX profile F */ +#define FAXPROFILE_J 3 /* !TIFF/FX FAX profile J */ +#define FAXPROFILE_C 4 /* !TIFF/FX FAX profile C */ +#define FAXPROFILE_L 5 /* !TIFF/FX FAX profile L */ +#define FAXPROFILE_M 6 /* !TIFF/FX FAX profile LM */ +#define TIFFTAG_CODINGMETHODS 403 /* !TIFF/FX coding methods */ +#define CODINGMETHODS_T4_1D (1 << 1) /* !T.4 1D */ +#define CODINGMETHODS_T4_2D (1 << 2) /* !T.4 2D */ +#define CODINGMETHODS_T6 (1 << 3) /* !T.6 */ +#define CODINGMETHODS_T85 (1 << 4) /* !T.85 JBIG */ +#define CODINGMETHODS_T42 (1 << 5) /* !T.42 JPEG */ +#define CODINGMETHODS_T43 (1 << 6) /* !T.43 colour by layered JBIG */ +#define TIFFTAG_VERSIONYEAR 404 /* !TIFF/FX version year */ +#define TIFFTAG_MODENUMBER 405 /* !TIFF/FX mode number */ +#define TIFFTAG_DECODE 433 /* !TIFF/FX decode */ +#define TIFFTAG_IMAGEBASECOLOR 434 /* !TIFF/FX image base colour */ +#define TIFFTAG_T82OPTIONS 435 /* !TIFF/FX T.82 options */ /* * Tags 512-521 are obsoleted by Technical Note #2 which specifies a * revised JPEG-in-TIFF scheme. @@ -331,7 +358,7 @@ typedef enum { #define TIFFTAG_JPEGRESTARTINTERVAL 515 /* !restart interval length */ #define TIFFTAG_JPEGLOSSLESSPREDICTORS 517 /* !lossless proc predictor */ #define TIFFTAG_JPEGPOINTTRANSFORM 518 /* !lossless point transform */ -#define TIFFTAG_JPEGQTABLES 519 /* !Q matrice offsets */ +#define TIFFTAG_JPEGQTABLES 519 /* !Q matrix offsets */ #define TIFFTAG_JPEGDCTABLES 520 /* !DCT table offsets */ #define TIFFTAG_JPEGACTABLES 521 /* !AC coefficient offsets */ #define TIFFTAG_YCBCRCOEFFICIENTS 529 /* !RGB -> YCbCr transform */ @@ -340,11 +367,12 @@ typedef enum { #define YCBCRPOSITION_CENTERED 1 /* !as in PostScript Level 2 */ #define YCBCRPOSITION_COSITED 2 /* !as in CCIR 601-1 */ #define TIFFTAG_REFERENCEBLACKWHITE 532 /* !colorimetry info */ +#define TIFFTAG_STRIPROWCOUNTS 559 /* !TIFF/FX strip row counts */ #define TIFFTAG_XMLPACKET 700 /* %XML packet - [Adobe XMP Specification, - January 2004 */ + [Adobe XMP Specification, + January 2004 */ #define TIFFTAG_OPIIMAGEID 32781 /* %OPI ImageID - [Adobe TIFF technote] */ + [Adobe TIFF technote] */ /* tags 32952-32956 are private tags registered to Island Graphics */ #define TIFFTAG_REFPTS 32953 /* image reference points */ #define TIFFTAG_REGIONTACKPOINT 32954 /* region-xform tack point */ @@ -358,7 +386,7 @@ typedef enum { /* tags 33300-33309 are private tags registered to Pixar */ /* * TIFFTAG_PIXAR_IMAGEFULLWIDTH and TIFFTAG_PIXAR_IMAGEFULLLENGTH - * are set when an image has been cropped out of a larger image. + * are set when an image has been cropped out of a larger image. * They reflect the size of the original uncropped image. * The TIFFTAG_XPOSITION and TIFFTAG_YPOSITION can be used * to determine the position of the smaller image in the larger one. @@ -375,6 +403,8 @@ typedef enum { #define TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA 33306 /* tag 33405 is a private tag registered to Eastman Kodak */ #define TIFFTAG_WRITERSERIALNUMBER 33405 /* device serial number */ +#define TIFFTAG_CFAREPEATPATTERNDIM 33421 /* dimensions of CFA pattern */ +#define TIFFTAG_CFAPATTERN 33422 /* color filter array pattern */ /* tag 33432 is listed in the 6.0 spec w/ unknown ownership */ #define TIFFTAG_COPYRIGHT 33432 /* copyright string */ /* IPTC TAG from RichTIFF specifications */ @@ -396,16 +426,17 @@ typedef enum { #define TIFFTAG_IT8COLORCHARACTERIZATION 34029 /* color character. table */ #define TIFFTAG_IT8HCUSAGE 34030 /* HC usage indicator */ #define TIFFTAG_IT8TRAPINDICATOR 34031 /* Trapping indicator - (untrapped=0, trapped=1) */ + (untrapped=0, trapped=1) */ #define TIFFTAG_IT8CMYKEQUIVALENT 34032 /* CMYK color equivalents */ /* tags 34232-34236 are private tags registered to Texas Instruments */ #define TIFFTAG_FRAMECOUNT 34232 /* Sequence Frame Count */ /* tag 34377 is private tag registered to Adobe for PhotoShop */ -#define TIFFTAG_PHOTOSHOP 34377 +#define TIFFTAG_PHOTOSHOP 34377 /* tags 34665, 34853 and 40965 are documented in EXIF specification */ #define TIFFTAG_EXIFIFD 34665 /* Pointer to EXIF private directory */ /* tag 34750 is a private tag registered to Adobe? */ #define TIFFTAG_ICCPROFILE 34675 /* ICC profile data */ +#define TIFFTAG_IMAGELAYER 34732 /* !TIFF/FX image layer information */ /* tag 34750 is a private tag registered to Pixel Magic */ #define TIFFTAG_JBIGOPTIONS 34750 /* JBIG options */ #define TIFFTAG_GPSIFD 34853 /* Pointer to GPS private directory */ @@ -424,80 +455,80 @@ typedef enum { #define TIFFTAG_DNGBACKWARDVERSION 50707 /* &DNG compatibility version */ #define TIFFTAG_UNIQUECAMERAMODEL 50708 /* &name for the camera model */ #define TIFFTAG_LOCALIZEDCAMERAMODEL 50709 /* &localized camera model - name */ + name */ #define TIFFTAG_CFAPLANECOLOR 50710 /* &CFAPattern->LinearRaw space - mapping */ + mapping */ #define TIFFTAG_CFALAYOUT 50711 /* &spatial layout of the CFA */ #define TIFFTAG_LINEARIZATIONTABLE 50712 /* &lookup table description */ #define TIFFTAG_BLACKLEVELREPEATDIM 50713 /* &repeat pattern size for - the BlackLevel tag */ + the BlackLevel tag */ #define TIFFTAG_BLACKLEVEL 50714 /* &zero light encoding level */ #define TIFFTAG_BLACKLEVELDELTAH 50715 /* &zero light encoding level - differences (columns) */ + differences (columns) */ #define TIFFTAG_BLACKLEVELDELTAV 50716 /* &zero light encoding level - differences (rows) */ + differences (rows) */ #define TIFFTAG_WHITELEVEL 50717 /* &fully saturated encoding - level */ + level */ #define TIFFTAG_DEFAULTSCALE 50718 /* &default scale factors */ #define TIFFTAG_DEFAULTCROPORIGIN 50719 /* &origin of the final image - area */ -#define TIFFTAG_DEFAULTCROPSIZE 50720 /* &size of the final image - area */ + area */ +#define TIFFTAG_DEFAULTCROPSIZE 50720 /* &size of the final image + area */ #define TIFFTAG_COLORMATRIX1 50721 /* &XYZ->reference color space - transformation matrix 1 */ + transformation matrix 1 */ #define TIFFTAG_COLORMATRIX2 50722 /* &XYZ->reference color space - transformation matrix 2 */ + transformation matrix 2 */ #define TIFFTAG_CAMERACALIBRATION1 50723 /* &calibration matrix 1 */ #define TIFFTAG_CAMERACALIBRATION2 50724 /* &calibration matrix 2 */ #define TIFFTAG_REDUCTIONMATRIX1 50725 /* &dimensionality reduction - matrix 1 */ + matrix 1 */ #define TIFFTAG_REDUCTIONMATRIX2 50726 /* &dimensionality reduction - matrix 2 */ + matrix 2 */ #define TIFFTAG_ANALOGBALANCE 50727 /* &gain applied the stored raw - values*/ + values*/ #define TIFFTAG_ASSHOTNEUTRAL 50728 /* &selected white balance in - linear reference space */ + linear reference space */ #define TIFFTAG_ASSHOTWHITEXY 50729 /* &selected white balance in - x-y chromaticity - coordinates */ + x-y chromaticity + coordinates */ #define TIFFTAG_BASELINEEXPOSURE 50730 /* &how much to move the zero - point */ + point */ #define TIFFTAG_BASELINENOISE 50731 /* &relative noise level */ #define TIFFTAG_BASELINESHARPNESS 50732 /* &relative amount of - sharpening */ + sharpening */ #define TIFFTAG_BAYERGREENSPLIT 50733 /* &how closely the values of - the green pixels in the - blue/green rows track the - values of the green pixels - in the red/green rows */ + the green pixels in the + blue/green rows track the + values of the green pixels + in the red/green rows */ #define TIFFTAG_LINEARRESPONSELIMIT 50734 /* &non-linear encoding range */ #define TIFFTAG_CAMERASERIALNUMBER 50735 /* &camera's serial number */ #define TIFFTAG_LENSINFO 50736 /* info about the lens */ #define TIFFTAG_CHROMABLURRADIUS 50737 /* &chroma blur radius */ #define TIFFTAG_ANTIALIASSTRENGTH 50738 /* &relative strength of the - camera's anti-alias filter */ + camera's anti-alias filter */ #define TIFFTAG_SHADOWSCALE 50739 /* &used by Adobe Camera Raw */ #define TIFFTAG_DNGPRIVATEDATA 50740 /* &manufacturer's private data */ #define TIFFTAG_MAKERNOTESAFETY 50741 /* &whether the EXIF MakerNote - tag is safe to preserve - along with the rest of the - EXIF data */ + tag is safe to preserve + along with the rest of the + EXIF data */ #define TIFFTAG_CALIBRATIONILLUMINANT1 50778 /* &illuminant 1 */ #define TIFFTAG_CALIBRATIONILLUMINANT2 50779 /* &illuminant 2 */ #define TIFFTAG_BESTQUALITYSCALE 50780 /* &best quality multiplier */ #define TIFFTAG_RAWDATAUNIQUEID 50781 /* &unique identifier for - the raw image data */ + the raw image data */ #define TIFFTAG_ORIGINALRAWFILENAME 50827 /* &file name of the original - raw file */ + raw file */ #define TIFFTAG_ORIGINALRAWFILEDATA 50828 /* &contents of the original - raw file */ + raw file */ #define TIFFTAG_ACTIVEAREA 50829 /* &active (non-masked) pixels - of the sensor */ + of the sensor */ #define TIFFTAG_MASKEDAREAS 50830 /* &list of coordinates - of fully masked pixels */ + of fully masked pixels */ #define TIFFTAG_ASSHOTICCPROFILE 50831 /* &these two tags used to */ #define TIFFTAG_ASSHOTPREPROFILEMATRIX 50832 /* map cameras's color space - into ICC profile space */ + into ICC profile space */ #define TIFFTAG_CURRENTICCPROFILE 50833 /* & */ #define TIFFTAG_CURRENTPREPROFILEMATRIX 50834 /* & */ /* tag 65535 is an undefined tag used by Eastman Kodak */ @@ -582,12 +613,12 @@ typedef enum { #define EXIFTAG_SPECTRALSENSITIVITY 34852 /* Spectral sensitivity */ #define EXIFTAG_ISOSPEEDRATINGS 34855 /* ISO speed rating */ #define EXIFTAG_OECF 34856 /* Optoelectric conversion - factor */ + factor */ #define EXIFTAG_EXIFVERSION 36864 /* Exif version */ #define EXIFTAG_DATETIMEORIGINAL 36867 /* Date and time of original - data generation */ + data generation */ #define EXIFTAG_DATETIMEDIGITIZED 36868 /* Date and time of digital - data generation */ + data generation */ #define EXIFTAG_COMPONENTSCONFIGURATION 37121 /* Meaning of each component */ #define EXIFTAG_COMPRESSEDBITSPERPIXEL 37122 /* Image compression mode */ #define EXIFTAG_SHUTTERSPEEDVALUE 37377 /* Shutter speed */ diff --git a/3rdparty/libtiff/tiffconf.h.cmake.in b/3rdparty/libtiff/tiffconf.h.cmake.in new file mode 100644 index 0000000000..de8a807eb1 --- /dev/null +++ b/3rdparty/libtiff/tiffconf.h.cmake.in @@ -0,0 +1,130 @@ +/* + Configuration defines for installed libtiff. + This file maintained for backward compatibility. Do not use definitions + from this file in your programs. +*/ + +#ifndef _TIFFCONF_ +#define _TIFFCONF_ + +/* Signed 16-bit type */ +#define TIFF_INT16_T @TIFF_INT16_T@ + +/* Signed 32-bit type */ +#define TIFF_INT32_T @TIFF_INT32_T@ + +/* Signed 64-bit type */ +#define TIFF_INT64_T @TIFF_INT64_T@ + +/* Signed 8-bit type */ +#define TIFF_INT8_T @TIFF_INT8_T@ + +/* Unsigned 16-bit type */ +#define TIFF_UINT16_T @TIFF_UINT16_T@ + +/* Unsigned 32-bit type */ +#define TIFF_UINT32_T @TIFF_UINT32_T@ + +/* Unsigned 64-bit type */ +#define TIFF_UINT64_T @TIFF_UINT64_T@ + +/* Unsigned 8-bit type */ +#define TIFF_UINT8_T @TIFF_UINT8_T@ + +/* Unsigned size type */ +#define TIFF_SIZE_T @TIFF_SIZE_T@ + +/* Signed size type */ +#define TIFF_SSIZE_T @TIFF_SSIZE_T@ + +/* Pointer difference type */ +#define TIFF_PTRDIFF_T @TIFF_PTRDIFF_T@ + +/* Define to 1 if the system has the type `int16'. */ +#cmakedefine HAVE_INT16 1 + +/* Define to 1 if the system has the type `int32'. */ +#cmakedefine HAVE_INT32 1 + +/* Define to 1 if the system has the type `int8'. */ +#cmakedefine HAVE_INT8 1 + +/* Compatibility stuff. */ + +/* Define as 0 or 1 according to the floating point format suported by the + machine */ +#cmakedefine HAVE_IEEEFP 1 + +/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */ +#define HOST_FILLORDER @HOST_FILLORDER@ + +/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian + (Intel) */ +#define HOST_BIGENDIAN @HOST_BIG_ENDIAN@ + +/* Support CCITT Group 3 & 4 algorithms */ +#cmakedefine CCITT_SUPPORT 1 + +/* Support JPEG compression (requires IJG JPEG library) */ +#cmakedefine JPEG_SUPPORT 1 + +/* Support JBIG compression (requires JBIG-KIT library) */ +#cmakedefine JBIG_SUPPORT + +/* Support LogLuv high dynamic range encoding */ +#cmakedefine LOGLUV_SUPPORT 1 + +/* Support LZW algorithm */ +#cmakedefine LZW_SUPPORT 1 + +/* Support NeXT 2-bit RLE algorithm */ +#cmakedefine NEXT_SUPPORT 1 + +/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation + fails with unpatched IJG JPEG library) */ +#cmakedefine OJPEG_SUPPORT 1 + +/* Support Macintosh PackBits algorithm */ +#cmakedefine PACKBITS_SUPPORT 1 + +/* Support Pixar log-format algorithm (requires Zlib) */ +#cmakedefine PIXARLOG_SUPPORT 1 + +/* Support ThunderScan 4-bit RLE algorithm */ +#cmakedefine THUNDER_SUPPORT 1 + +/* Support Deflate compression */ +#cmakedefine ZIP_SUPPORT 1 + +/* Support strip chopping (whether or not to convert single-strip uncompressed + images to mutiple strips of ~8Kb to reduce memory usage) */ +#cmakedefine STRIPCHOP_DEFAULT 1 + +/* Enable SubIFD tag (330) support */ +#cmakedefine SUBIFD_SUPPORT 1 + +/* Treat extra sample as alpha (default enabled). The RGBA interface will + treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many + packages produce RGBA files but don't mark the alpha properly. */ +#cmakedefine DEFAULT_EXTRASAMPLE_AS_ALPHA 1 + +/* Pick up YCbCr subsampling info from the JPEG data stream to support files + lacking the tag (default enabled). */ +#cmakedefine CHECK_JPEG_YCBCR_SUBSAMPLING 1 + +/* Support MS MDI magic number files as TIFF */ +#cmakedefine MDI_SUPPORT 1 + +/* + * Feature support definitions. + * XXX: These macros are obsoleted. Don't use them in your apps! + * Macros stays here for backward compatibility and should be always defined. + */ +#define COLORIMETRY_SUPPORT +#define YCBCR_SUPPORT +#define CMYK_SUPPORT +#define ICC_SUPPORT +#define PHOTOSHOP_SUPPORT +#define IPTC_SUPPORT + +#endif /* _TIFFCONF_ */ diff --git a/3rdparty/libtiff/tiffio.h b/3rdparty/libtiff/tiffio.h index 75fa661bc4..ef61b5c06a 100644 --- a/3rdparty/libtiff/tiffio.h +++ b/3rdparty/libtiff/tiffio.h @@ -1,4 +1,4 @@ -/* $Id: tiffio.h,v 1.90 2012-06-06 04:58:00 fwarmerdam Exp $ */ +/* $Id: tiffio.h,v 1.94 2017-01-11 19:02:49 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler @@ -120,7 +120,7 @@ typedef void* thandle_t; /* client data handle */ #define TIFFPRINT_JPEGACTABLES 0x200 /* JPEG AC tables */ #define TIFFPRINT_JPEGDCTABLES 0x200 /* JPEG DC tables */ -/* +/* * Colour conversion stuff */ @@ -138,39 +138,39 @@ typedef void* thandle_t; /* client data handle */ typedef unsigned char TIFFRGBValue; /* 8-bit samples */ typedef struct { - float d_mat[3][3]; /* XYZ -> luminance matrix */ - float d_YCR; /* Light o/p for reference white */ - float d_YCG; - float d_YCB; - uint32 d_Vrwr; /* Pixel values for ref. white */ - uint32 d_Vrwg; - uint32 d_Vrwb; - float d_Y0R; /* Residual light for black pixel */ - float d_Y0G; - float d_Y0B; - float d_gammaR; /* Gamma values for the three guns */ - float d_gammaG; - float d_gammaB; + float d_mat[3][3]; /* XYZ -> luminance matrix */ + float d_YCR; /* Light o/p for reference white */ + float d_YCG; + float d_YCB; + uint32 d_Vrwr; /* Pixel values for ref. white */ + uint32 d_Vrwg; + uint32 d_Vrwb; + float d_Y0R; /* Residual light for black pixel */ + float d_Y0G; + float d_Y0B; + float d_gammaR; /* Gamma values for the three guns */ + float d_gammaG; + float d_gammaB; } TIFFDisplay; typedef struct { /* YCbCr->RGB support */ - TIFFRGBValue* clamptab; /* range clamping table */ - int* Cr_r_tab; - int* Cb_b_tab; - int32* Cr_g_tab; - int32* Cb_g_tab; - int32* Y_tab; + TIFFRGBValue* clamptab; /* range clamping table */ + int* Cr_r_tab; + int* Cb_b_tab; + int32* Cr_g_tab; + int32* Cb_g_tab; + int32* Y_tab; } TIFFYCbCrToRGB; typedef struct { /* CIE Lab 1976->RGB support */ - int range; /* Size of conversion table */ + int range; /* Size of conversion table */ #define CIELABTORGB_TABLE_RANGE 1500 - float rstep, gstep, bstep; - float X0, Y0, Z0; /* Reference white point */ - TIFFDisplay display; - float Yr2r[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yr to r */ - float Yg2g[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yg to g */ - float Yb2b[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yb to b */ + float rstep, gstep, bstep; + float X0, Y0, Z0; /* Reference white point */ + TIFFDisplay display; + float Yr2r[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yr to r */ + float Yg2g[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yg to g */ + float Yb2b[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yb to b */ } TIFFCIELabToRGB; /* @@ -180,7 +180,7 @@ typedef struct _TIFFRGBAImage TIFFRGBAImage; /* * The image reading and conversion routines invoke * ``put routines'' to copy/image/whatever tiles of - * raw image data. A default set of routines are + * raw image data. A default set of routines are * provided to convert/copy raw image data to 8-bit * packed ABGR format rasters. Applications can supply * alternate routines that unpack the data into a @@ -189,47 +189,47 @@ typedef struct _TIFFRGBAImage TIFFRGBAImage; */ typedef void (*tileContigRoutine) (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, - unsigned char*); + unsigned char*); typedef void (*tileSeparateRoutine) (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32, - unsigned char*, unsigned char*, unsigned char*, unsigned char*); + unsigned char*, unsigned char*, unsigned char*, unsigned char*); /* * RGBA-reader state. */ struct _TIFFRGBAImage { - TIFF* tif; /* image handle */ - int stoponerr; /* stop on read error */ - int isContig; /* data is packed/separate */ - int alpha; /* type of alpha data present */ - uint32 width; /* image width */ - uint32 height; /* image height */ - uint16 bitspersample; /* image bits/sample */ - uint16 samplesperpixel; /* image samples/pixel */ - uint16 orientation; /* image orientation */ - uint16 req_orientation; /* requested orientation */ - uint16 photometric; /* image photometric interp */ - uint16* redcmap; /* colormap pallete */ - uint16* greencmap; - uint16* bluecmap; - /* get image data routine */ - int (*get)(TIFFRGBAImage*, uint32*, uint32, uint32); - /* put decoded strip/tile */ - union { - void (*any)(TIFFRGBAImage*); - tileContigRoutine contig; - tileSeparateRoutine separate; - } put; - TIFFRGBValue* Map; /* sample mapping array */ - uint32** BWmap; /* black&white map */ - uint32** PALmap; /* palette image map */ - TIFFYCbCrToRGB* ycbcr; /* YCbCr conversion state */ - TIFFCIELabToRGB* cielab; /* CIE L*a*b conversion state */ + TIFF* tif; /* image handle */ + int stoponerr; /* stop on read error */ + int isContig; /* data is packed/separate */ + int alpha; /* type of alpha data present */ + uint32 width; /* image width */ + uint32 height; /* image height */ + uint16 bitspersample; /* image bits/sample */ + uint16 samplesperpixel; /* image samples/pixel */ + uint16 orientation; /* image orientation */ + uint16 req_orientation; /* requested orientation */ + uint16 photometric; /* image photometric interp */ + uint16* redcmap; /* colormap palette */ + uint16* greencmap; + uint16* bluecmap; + /* get image data routine */ + int (*get)(TIFFRGBAImage*, uint32*, uint32, uint32); + /* put decoded strip/tile */ + union { + void (*any)(TIFFRGBAImage*); + tileContigRoutine contig; + tileSeparateRoutine separate; + } put; + TIFFRGBValue* Map; /* sample mapping array */ + uint32** BWmap; /* black&white map */ + uint32** PALmap; /* palette image map */ + TIFFYCbCrToRGB* ycbcr; /* YCbCr conversion state */ + TIFFCIELabToRGB* cielab; /* CIE L*a*b conversion state */ - uint8* UaToAa; /* Unassociated alpha to associated alpha convertion LUT */ - uint8* Bitdepth16To8; /* LUT for conversion from 16bit to 8bit values */ + uint8* UaToAa; /* Unassociated alpha to associated alpha conversion LUT */ + uint8* Bitdepth16To8; /* LUT for conversion from 16bit to 8bit values */ - int row_offset; - int col_offset; + int row_offset; + int col_offset; }; /* @@ -250,9 +250,9 @@ struct _TIFFRGBAImage { */ typedef int (*TIFFInitMethod)(TIFF*, int); typedef struct { - char* name; - uint16 scheme; - TIFFInitMethod init; + char* name; + uint16 scheme; + TIFFInitMethod init; } TIFFCodec; #include @@ -293,6 +293,7 @@ extern TIFFCodec* TIFFGetConfiguredCODECs(void); */ extern void* _TIFFmalloc(tmsize_t s); +extern void* _TIFFcalloc(tmsize_t nmemb, tmsize_t siz); extern void* _TIFFrealloc(void* p, tmsize_t s); extern void _TIFFmemset(void* p, int v, tmsize_t c); extern void _TIFFmemcpy(void* d, const void* s, tmsize_t c); @@ -304,7 +305,7 @@ extern void _TIFFfree(void* p); */ extern int TIFFGetTagListCount( TIFF * ); extern uint32 TIFFGetTagListEntry( TIFF *, int tag_index ); - + #define TIFF_ANY TIFF_NOTYPE /* for field descriptor searching */ #define TIFF_VARIABLE -1 /* marker for variable length tags */ #define TIFF_SPP -2 /* marker for SamplesPerPixel tags */ @@ -319,6 +320,13 @@ extern const TIFFField* TIFFFindField(TIFF *, uint32, TIFFDataType); extern const TIFFField* TIFFFieldWithTag(TIFF*, uint32); extern const TIFFField* TIFFFieldWithName(TIFF*, const char *); +extern uint32 TIFFFieldTag(const TIFFField*); +extern const char* TIFFFieldName(const TIFFField*); +extern TIFFDataType TIFFFieldDataType(const TIFFField*); +extern int TIFFFieldPassCount(const TIFFField*); +extern int TIFFFieldReadCount(const TIFFField*); +extern int TIFFFieldWriteCount(const TIFFField*); + typedef int (*TIFFVSetMethod)(TIFF*, uint32, va_list); typedef int (*TIFFVGetMethod)(TIFF*, uint32, va_list); typedef void (*TIFFPrintMethod)(TIFF*, FILE*, long); @@ -375,7 +383,7 @@ extern int TIFFIsMSB2LSB(TIFF*); extern int TIFFIsBigEndian(TIFF*); extern TIFFReadWriteProc TIFFGetReadProc(TIFF*); extern TIFFReadWriteProc TIFFGetWriteProc(TIFF*); -extern TIFFSeekProc TIFFGetSeekProc(TIFF*); +extern TIFFSeekProc TIFFGetSeekProc(TIFF*); extern TIFFCloseProc TIFFGetCloseProc(TIFF*); extern TIFFSizeProc TIFFGetSizeProc(TIFF*); extern TIFFMapFileProc TIFFGetMapFileProc(TIFF*); @@ -387,7 +395,7 @@ extern uint64 TIFFCurrentDirOffset(TIFF*); extern uint32 TIFFCurrentStrip(TIFF*); extern uint32 TIFFCurrentTile(TIFF* tif); extern int TIFFReadBufferSetup(TIFF* tif, void* bp, tmsize_t size); -extern int TIFFWriteBufferSetup(TIFF* tif, void* bp, tmsize_t size); +extern int TIFFWriteBufferSetup(TIFF* tif, void* bp, tmsize_t size); extern int TIFFSetupStrips(TIFF *); extern int TIFFWriteCheck(TIFF*, int, const char *); extern void TIFFFreeDirectory(TIFF*); @@ -423,6 +431,8 @@ extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, int, int); extern int TIFFReadRGBAStrip(TIFF*, uint32, uint32 * ); extern int TIFFReadRGBATile(TIFF*, uint32, uint32, uint32 * ); +extern int TIFFReadRGBAStripExt(TIFF*, uint32, uint32 *, int stop_on_error ); +extern int TIFFReadRGBATileExt(TIFF*, uint32, uint32, uint32 *, int stop_on_error ); extern int TIFFRGBAImageOK(TIFF*, char [1024]); extern int TIFFRGBAImageBegin(TIFFRGBAImage*, TIFF*, int, char [1024]); extern int TIFFRGBAImageGet(TIFFRGBAImage*, uint32*, uint32, uint32); @@ -433,11 +443,11 @@ extern TIFF* TIFFOpenW(const wchar_t*, const char*); # endif /* __WIN32__ */ extern TIFF* TIFFFdOpen(int, const char*, const char*); extern TIFF* TIFFClientOpen(const char*, const char*, - thandle_t, - TIFFReadWriteProc, TIFFReadWriteProc, - TIFFSeekProc, TIFFCloseProc, - TIFFSizeProc, - TIFFMapFileProc, TIFFUnmapFileProc); + thandle_t, + TIFFReadWriteProc, TIFFReadWriteProc, + TIFFSeekProc, TIFFCloseProc, + TIFFSizeProc, + TIFFMapFileProc, TIFFUnmapFileProc); extern const char* TIFFFileName(TIFF*); extern const char* TIFFSetFileName(TIFF*, const char *); extern void TIFFError(const char*, const char*, ...) __attribute__((__format__ (__printf__,2,3))); @@ -452,18 +462,18 @@ extern TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc); extern uint32 TIFFComputeTile(TIFF* tif, uint32 x, uint32 y, uint32 z, uint16 s); extern int TIFFCheckTile(TIFF* tif, uint32 x, uint32 y, uint32 z, uint16 s); extern uint32 TIFFNumberOfTiles(TIFF*); -extern tmsize_t TIFFReadTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s); +extern tmsize_t TIFFReadTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s); extern tmsize_t TIFFWriteTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s); extern uint32 TIFFComputeStrip(TIFF*, uint32, uint16); extern uint32 TIFFNumberOfStrips(TIFF*); extern tmsize_t TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size); -extern tmsize_t TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size); -extern tmsize_t TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size); -extern tmsize_t TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size); +extern tmsize_t TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size); +extern tmsize_t TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size); +extern tmsize_t TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size); extern tmsize_t TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc); -extern tmsize_t TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc); -extern tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc); -extern tmsize_t TIFFWriteRawTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc); +extern tmsize_t TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc); +extern tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc); +extern tmsize_t TIFFWriteRawTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc); extern int TIFFDataWidth(TIFFDataType); /* table of tag datatype widths */ extern void TIFFSetWriteOffset(TIFF* tif, toff_t off); extern void TIFFSwabShort(uint16*); @@ -522,18 +532,18 @@ extern void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *, uint32, int32, int32, * libtiff versions. ****************************************************************************/ typedef struct { - ttag_t field_tag; /* field's tag */ - short field_readcount; /* read count/TIFF_VARIABLE/TIFF_SPP */ - short field_writecount; /* write count/TIFF_VARIABLE */ - TIFFDataType field_type; /* type of associated data */ + ttag_t field_tag; /* field's tag */ + short field_readcount; /* read count/TIFF_VARIABLE/TIFF_SPP */ + short field_writecount; /* write count/TIFF_VARIABLE */ + TIFFDataType field_type; /* type of associated data */ unsigned short field_bit; /* bit in fieldsset bit vector */ - unsigned char field_oktochange; /* if true, can change while writing */ - unsigned char field_passcount; /* if true, pass dir count on set */ - char *field_name; /* ASCII name */ + unsigned char field_oktochange; /* if true, can change while writing */ + unsigned char field_passcount; /* if true, pass dir count on set */ + char *field_name; /* ASCII name */ } TIFFFieldInfo; extern int TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], uint32); - + #if defined(c_plusplus) || defined(__cplusplus) } #endif diff --git a/3rdparty/libtiff/tiffio.hxx b/3rdparty/libtiff/tiffio.hxx index 5cb68ab49b..ed994f1156 100644 --- a/3rdparty/libtiff/tiffio.hxx +++ b/3rdparty/libtiff/tiffio.hxx @@ -4,23 +4,23 @@ * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ diff --git a/3rdparty/libtiff/tiffiop.h b/3rdparty/libtiff/tiffiop.h index 6116da3ce7..daa291c083 100644 --- a/3rdparty/libtiff/tiffiop.h +++ b/3rdparty/libtiff/tiffiop.h @@ -1,26 +1,26 @@ -/* $Id: tiffiop.h,v 1.84 2012-05-30 01:50:17 fwarmerdam Exp $ */ +/* $Id: tiffiop.h,v 1.95 2017-09-07 14:02:52 erouault Exp $ */ /* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * - * Permission to use, copy, modify, distribute, and sell this software and + * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. - * - * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, - * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - * + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF - * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ @@ -47,14 +47,20 @@ #ifdef HAVE_ASSERT_H # include #else -# define assert(x) +# define assert(x) #endif #ifdef HAVE_SEARCH_H # include #else extern void *lfind(const void *, const void *, size_t *, size_t, - int (*)(const void *, const void *)); + int (*)(const void *, const void *)); +#endif + +#if !defined(HAVE_SNPRINTF) && !defined(HAVE__SNPRINTF) +#undef snprintf +#define snprintf _TIFF_snprintf_f +extern int snprintf(char* str, size_t size, const char* format, ...); #endif #include "tiffio.h" @@ -80,7 +86,7 @@ typedef struct client_info { /* * Typedefs for ``method pointers'' used internally. - * these are depriciated and provided only for backwards compatibility + * these are deprecated and provided only for backwards compatibility. */ typedef unsigned char tidataval_t; /* internal image data value type */ typedef tidataval_t* tidata_t; /* reference to internal image data */ @@ -95,112 +101,112 @@ typedef uint32 (*TIFFStripMethod)(TIFF*, uint32); typedef void (*TIFFTileMethod)(TIFF*, uint32*, uint32*); struct tiff { - char* tif_name; /* name of open file */ - int tif_fd; /* open file descriptor */ - int tif_mode; /* open mode (O_*) */ - uint32 tif_flags; - #define TIFF_FILLORDER 0x00003 /* natural bit fill order for machine */ - #define TIFF_DIRTYHEADER 0x00004 /* header must be written on close */ - #define TIFF_DIRTYDIRECT 0x00008 /* current directory must be written */ - #define TIFF_BUFFERSETUP 0x00010 /* data buffers setup */ - #define TIFF_CODERSETUP 0x00020 /* encoder/decoder setup done */ - #define TIFF_BEENWRITING 0x00040 /* written 1+ scanlines to file */ - #define TIFF_SWAB 0x00080 /* byte swap file information */ - #define TIFF_NOBITREV 0x00100 /* inhibit bit reversal logic */ - #define TIFF_MYBUFFER 0x00200 /* my raw data buffer; free on close */ - #define TIFF_ISTILED 0x00400 /* file is tile, not strip- based */ - #define TIFF_MAPPED 0x00800 /* file is mapped into memory */ - #define TIFF_POSTENCODE 0x01000 /* need call to postencode routine */ - #define TIFF_INSUBIFD 0x02000 /* currently writing a subifd */ - #define TIFF_UPSAMPLED 0x04000 /* library is doing data up-sampling */ - #define TIFF_STRIPCHOP 0x08000 /* enable strip chopping support */ - #define TIFF_HEADERONLY 0x10000 /* read header only, do not process the first directory */ - #define TIFF_NOREADRAW 0x20000 /* skip reading of raw uncompressed image data */ - #define TIFF_INCUSTOMIFD 0x40000 /* currently writing a custom IFD */ - #define TIFF_BIGTIFF 0x80000 /* read/write bigtiff */ - #define TIFF_BUF4WRITE 0x100000 /* rawcc bytes are for writing */ - #define TIFF_DIRTYSTRIP 0x200000 /* stripoffsets/stripbytecount dirty*/ - #define TIFF_PERSAMPLE 0x400000 /* get/set per sample tags as arrays */ - #define TIFF_BUFFERMMAP 0x800000 /* read buffer (tif_rawdata) points into mmap() memory */ - uint64 tif_diroff; /* file offset of current directory */ - uint64 tif_nextdiroff; /* file offset of following directory */ - uint64* tif_dirlist; /* list of offsets to already seen directories to prevent IFD looping */ - uint16 tif_dirlistsize; /* number of entires in offset list */ - uint16 tif_dirnumber; /* number of already seen directories */ - TIFFDirectory tif_dir; /* internal rep of current directory */ - TIFFDirectory tif_customdir; /* custom IFDs are separated from the main ones */ - union { - TIFFHeaderCommon common; - TIFFHeaderClassic classic; - TIFFHeaderBig big; - } tif_header; - uint16 tif_header_size; /* file's header block and its length */ - uint32 tif_row; /* current scanline */ - uint16 tif_curdir; /* current directory (index) */ - uint32 tif_curstrip; /* current strip for read/write */ - uint64 tif_curoff; /* current offset for read/write */ - uint64 tif_dataoff; /* current offset for writing dir */ - /* SubIFD support */ - uint16 tif_nsubifd; /* remaining subifds to write */ - uint64 tif_subifdoff; /* offset for patching SubIFD link */ - /* tiling support */ - uint32 tif_col; /* current column (offset by row too) */ - uint32 tif_curtile; /* current tile for read/write */ - tmsize_t tif_tilesize; /* # of bytes in a tile */ - /* compression scheme hooks */ - int tif_decodestatus; - TIFFBoolMethod tif_fixuptags; /* called in TIFFReadDirectory */ - TIFFBoolMethod tif_setupdecode; /* called once before predecode */ - TIFFPreMethod tif_predecode; /* pre- row/strip/tile decoding */ - TIFFBoolMethod tif_setupencode; /* called once before preencode */ - int tif_encodestatus; - TIFFPreMethod tif_preencode; /* pre- row/strip/tile encoding */ - TIFFBoolMethod tif_postencode; /* post- row/strip/tile encoding */ - TIFFCodeMethod tif_decoderow; /* scanline decoding routine */ - TIFFCodeMethod tif_encoderow; /* scanline encoding routine */ - TIFFCodeMethod tif_decodestrip; /* strip decoding routine */ - TIFFCodeMethod tif_encodestrip; /* strip encoding routine */ - TIFFCodeMethod tif_decodetile; /* tile decoding routine */ - TIFFCodeMethod tif_encodetile; /* tile encoding routine */ - TIFFVoidMethod tif_close; /* cleanup-on-close routine */ - TIFFSeekMethod tif_seek; /* position within a strip routine */ - TIFFVoidMethod tif_cleanup; /* cleanup state routine */ - TIFFStripMethod tif_defstripsize; /* calculate/constrain strip size */ - TIFFTileMethod tif_deftilesize; /* calculate/constrain tile size */ - uint8* tif_data; /* compression scheme private data */ - /* input/output buffering */ - tmsize_t tif_scanlinesize; /* # of bytes in a scanline */ - tmsize_t tif_scanlineskew; /* scanline skew for reading strips */ - uint8* tif_rawdata; /* raw data buffer */ - tmsize_t tif_rawdatasize; /* # of bytes in raw data buffer */ + char* tif_name; /* name of open file */ + int tif_fd; /* open file descriptor */ + int tif_mode; /* open mode (O_*) */ + uint32 tif_flags; + #define TIFF_FILLORDER 0x00003U /* natural bit fill order for machine */ + #define TIFF_DIRTYHEADER 0x00004U /* header must be written on close */ + #define TIFF_DIRTYDIRECT 0x00008U /* current directory must be written */ + #define TIFF_BUFFERSETUP 0x00010U /* data buffers setup */ + #define TIFF_CODERSETUP 0x00020U /* encoder/decoder setup done */ + #define TIFF_BEENWRITING 0x00040U /* written 1+ scanlines to file */ + #define TIFF_SWAB 0x00080U /* byte swap file information */ + #define TIFF_NOBITREV 0x00100U /* inhibit bit reversal logic */ + #define TIFF_MYBUFFER 0x00200U /* my raw data buffer; free on close */ + #define TIFF_ISTILED 0x00400U /* file is tile, not strip- based */ + #define TIFF_MAPPED 0x00800U /* file is mapped into memory */ + #define TIFF_POSTENCODE 0x01000U /* need call to postencode routine */ + #define TIFF_INSUBIFD 0x02000U /* currently writing a subifd */ + #define TIFF_UPSAMPLED 0x04000U /* library is doing data up-sampling */ + #define TIFF_STRIPCHOP 0x08000U /* enable strip chopping support */ + #define TIFF_HEADERONLY 0x10000U /* read header only, do not process the first directory */ + #define TIFF_NOREADRAW 0x20000U /* skip reading of raw uncompressed image data */ + #define TIFF_INCUSTOMIFD 0x40000U /* currently writing a custom IFD */ + #define TIFF_BIGTIFF 0x80000U /* read/write bigtiff */ + #define TIFF_BUF4WRITE 0x100000U /* rawcc bytes are for writing */ + #define TIFF_DIRTYSTRIP 0x200000U /* stripoffsets/stripbytecount dirty*/ + #define TIFF_PERSAMPLE 0x400000U /* get/set per sample tags as arrays */ + #define TIFF_BUFFERMMAP 0x800000U /* read buffer (tif_rawdata) points into mmap() memory */ + uint64 tif_diroff; /* file offset of current directory */ + uint64 tif_nextdiroff; /* file offset of following directory */ + uint64* tif_dirlist; /* list of offsets to already seen directories to prevent IFD looping */ + uint16 tif_dirlistsize; /* number of entries in offset list */ + uint16 tif_dirnumber; /* number of already seen directories */ + TIFFDirectory tif_dir; /* internal rep of current directory */ + TIFFDirectory tif_customdir; /* custom IFDs are separated from the main ones */ + union { + TIFFHeaderCommon common; + TIFFHeaderClassic classic; + TIFFHeaderBig big; + } tif_header; + uint16 tif_header_size; /* file's header block and its length */ + uint32 tif_row; /* current scanline */ + uint16 tif_curdir; /* current directory (index) */ + uint32 tif_curstrip; /* current strip for read/write */ + uint64 tif_curoff; /* current offset for read/write */ + uint64 tif_dataoff; /* current offset for writing dir */ + /* SubIFD support */ + uint16 tif_nsubifd; /* remaining subifds to write */ + uint64 tif_subifdoff; /* offset for patching SubIFD link */ + /* tiling support */ + uint32 tif_col; /* current column (offset by row too) */ + uint32 tif_curtile; /* current tile for read/write */ + tmsize_t tif_tilesize; /* # of bytes in a tile */ + /* compression scheme hooks */ + int tif_decodestatus; + TIFFBoolMethod tif_fixuptags; /* called in TIFFReadDirectory */ + TIFFBoolMethod tif_setupdecode; /* called once before predecode */ + TIFFPreMethod tif_predecode; /* pre- row/strip/tile decoding */ + TIFFBoolMethod tif_setupencode; /* called once before preencode */ + int tif_encodestatus; + TIFFPreMethod tif_preencode; /* pre- row/strip/tile encoding */ + TIFFBoolMethod tif_postencode; /* post- row/strip/tile encoding */ + TIFFCodeMethod tif_decoderow; /* scanline decoding routine */ + TIFFCodeMethod tif_encoderow; /* scanline encoding routine */ + TIFFCodeMethod tif_decodestrip; /* strip decoding routine */ + TIFFCodeMethod tif_encodestrip; /* strip encoding routine */ + TIFFCodeMethod tif_decodetile; /* tile decoding routine */ + TIFFCodeMethod tif_encodetile; /* tile encoding routine */ + TIFFVoidMethod tif_close; /* cleanup-on-close routine */ + TIFFSeekMethod tif_seek; /* position within a strip routine */ + TIFFVoidMethod tif_cleanup; /* cleanup state routine */ + TIFFStripMethod tif_defstripsize; /* calculate/constrain strip size */ + TIFFTileMethod tif_deftilesize; /* calculate/constrain tile size */ + uint8* tif_data; /* compression scheme private data */ + /* input/output buffering */ + tmsize_t tif_scanlinesize; /* # of bytes in a scanline */ + tmsize_t tif_scanlineskew; /* scanline skew for reading strips */ + uint8* tif_rawdata; /* raw data buffer */ + tmsize_t tif_rawdatasize; /* # of bytes in raw data buffer */ tmsize_t tif_rawdataoff; /* rawdata offset within strip */ tmsize_t tif_rawdataloaded;/* amount of data in rawdata */ - uint8* tif_rawcp; /* current spot in raw buffer */ - tmsize_t tif_rawcc; /* bytes unread from raw buffer */ - /* memory-mapped file support */ - uint8* tif_base; /* base of mapped file */ - tmsize_t tif_size; /* size of mapped file region (bytes, thus tmsize_t) */ - TIFFMapFileProc tif_mapproc; /* map file method */ - TIFFUnmapFileProc tif_unmapproc; /* unmap file method */ - /* input/output callback methods */ - thandle_t tif_clientdata; /* callback parameter */ - TIFFReadWriteProc tif_readproc; /* read method */ - TIFFReadWriteProc tif_writeproc; /* write method */ - TIFFSeekProc tif_seekproc; /* lseek method */ - TIFFCloseProc tif_closeproc; /* close method */ - TIFFSizeProc tif_sizeproc; /* filesize method */ - /* post-decoding support */ - TIFFPostMethod tif_postdecode; /* post decoding routine */ - /* tag support */ - TIFFField** tif_fields; /* sorted table of registered tags */ - size_t tif_nfields; /* # entries in registered tag table */ - const TIFFField* tif_foundfield; /* cached pointer to already found tag */ - TIFFTagMethods tif_tagmethods; /* tag get/set/print routines */ - TIFFClientInfoLink* tif_clientinfo; /* extra client information. */ - /* Backward compatibility stuff. We need these two fields for - * setting up an old tag extension scheme. */ - TIFFFieldArray* tif_fieldscompat; - size_t tif_nfieldscompat; + uint8* tif_rawcp; /* current spot in raw buffer */ + tmsize_t tif_rawcc; /* bytes unread from raw buffer */ + /* memory-mapped file support */ + uint8* tif_base; /* base of mapped file */ + tmsize_t tif_size; /* size of mapped file region (bytes, thus tmsize_t) */ + TIFFMapFileProc tif_mapproc; /* map file method */ + TIFFUnmapFileProc tif_unmapproc; /* unmap file method */ + /* input/output callback methods */ + thandle_t tif_clientdata; /* callback parameter */ + TIFFReadWriteProc tif_readproc; /* read method */ + TIFFReadWriteProc tif_writeproc; /* write method */ + TIFFSeekProc tif_seekproc; /* lseek method */ + TIFFCloseProc tif_closeproc; /* close method */ + TIFFSizeProc tif_sizeproc; /* filesize method */ + /* post-decoding support */ + TIFFPostMethod tif_postdecode; /* post decoding routine */ + /* tag support */ + TIFFField** tif_fields; /* sorted table of registered tags */ + size_t tif_nfields; /* # entries in registered tag table */ + const TIFFField* tif_foundfield; /* cached pointer to already found tag */ + TIFFTagMethods tif_tagmethods; /* tag get/set/print routines */ + TIFFClientInfoLink* tif_clientinfo; /* extra client information. */ + /* Backward compatibility stuff. We need these two fields for + * setting up an old tag extension scheme. */ + TIFFFieldArray* tif_fieldscompat; + size_t tif_nfieldscompat; }; #define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */ @@ -210,40 +216,43 @@ struct tiff { #define isFillOrder(tif, o) (((tif)->tif_flags & (o)) != 0) #define isUpSampled(tif) (((tif)->tif_flags & TIFF_UPSAMPLED) != 0) #define TIFFReadFile(tif, buf, size) \ - ((*(tif)->tif_readproc)((tif)->tif_clientdata,(buf),(size))) + ((*(tif)->tif_readproc)((tif)->tif_clientdata,(buf),(size))) #define TIFFWriteFile(tif, buf, size) \ - ((*(tif)->tif_writeproc)((tif)->tif_clientdata,(buf),(size))) + ((*(tif)->tif_writeproc)((tif)->tif_clientdata,(buf),(size))) #define TIFFSeekFile(tif, off, whence) \ - ((*(tif)->tif_seekproc)((tif)->tif_clientdata,(off),(whence))) + ((*(tif)->tif_seekproc)((tif)->tif_clientdata,(off),(whence))) #define TIFFCloseFile(tif) \ - ((*(tif)->tif_closeproc)((tif)->tif_clientdata)) + ((*(tif)->tif_closeproc)((tif)->tif_clientdata)) #define TIFFGetFileSize(tif) \ - ((*(tif)->tif_sizeproc)((tif)->tif_clientdata)) + ((*(tif)->tif_sizeproc)((tif)->tif_clientdata)) #define TIFFMapFileContents(tif, paddr, psize) \ - ((*(tif)->tif_mapproc)((tif)->tif_clientdata,(paddr),(psize))) + ((*(tif)->tif_mapproc)((tif)->tif_clientdata,(paddr),(psize))) #define TIFFUnmapFileContents(tif, addr, size) \ - ((*(tif)->tif_unmapproc)((tif)->tif_clientdata,(addr),(size))) + ((*(tif)->tif_unmapproc)((tif)->tif_clientdata,(addr),(size))) /* * Default Read/Seek/Write definitions. */ #ifndef ReadOK #define ReadOK(tif, buf, size) \ - (TIFFReadFile((tif),(buf),(size))==(size)) + (TIFFReadFile((tif),(buf),(size))==(size)) #endif #ifndef SeekOK -#define SeekOK(tif, off) \ - (TIFFSeekFile((tif),(off),SEEK_SET)==(off)) +#define SeekOK(tif, off) _TIFFSeekOK(tif, off) #endif #ifndef WriteOK #define WriteOK(tif, buf, size) \ - (TIFFWriteFile((tif),(buf),(size))==(size)) + (TIFFWriteFile((tif),(buf),(size))==(size)) #endif /* NB: the uint32 casts are to silence certain ANSI-C compilers */ #define TIFFhowmany_32(x, y) (((uint32)x < (0xffffffff - (uint32)(y-1))) ? \ - ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y))) : \ - 0U) + ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y))) : \ + 0U) +/* Variant of TIFFhowmany_32() that doesn't return 0 if x close to MAXUINT. */ +/* Caution: TIFFhowmany_32_maxuint_compat(x,y)*y might overflow */ +#define TIFFhowmany_32_maxuint_compat(x, y) \ + (((uint32)(x) / (uint32)(y)) + ((((uint32)(x) % (uint32)(y)) != 0) ? 1 : 0)) #define TIFFhowmany8_32(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3) #define TIFFroundup_32(x, y) (TIFFhowmany_32(x,y)*(y)) #define TIFFhowmany_64(x, y) ((((uint64)(x))+(((uint64)(y))-1))/((uint64)(y))) @@ -258,6 +267,60 @@ struct tiff { #define TIFFArrayCount(a) (sizeof (a) / sizeof ((a)[0])) +/* + Support for large files. + + Windows read/write APIs support only 'unsigned int' rather than 'size_t'. + Windows off_t is only 32-bit, even in 64-bit builds. +*/ +#if defined(HAVE_FSEEKO) +/* + Use fseeko() and ftello() if they are available since they use + 'off_t' rather than 'long'. It is wrong to use fseeko() and + ftello() only on systems with special LFS support since some systems + (e.g. FreeBSD) support a 64-bit off_t by default. + + For MinGW, __MSVCRT_VERSION__ must be at least 0x800 to expose these + interfaces. The MinGW compiler must support the requested version. MinGW + does not distribute the CRT (it is supplied by Microsoft) so the correct CRT + must be available on the target computer in order for the program to run. +*/ +#if defined(HAVE_FSEEKO) +# define fseek(stream,offset,whence) fseeko(stream,offset,whence) +# define ftell(stream,offset,whence) ftello(stream,offset,whence) +#endif +#endif +#if defined(__WIN32__) && \ + !(defined(_MSC_VER) && _MSC_VER < 1400) && \ + !(defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x800) +typedef unsigned int TIFFIOSize_t; +#define _TIFF_lseek_f(fildes,offset,whence) _lseeki64(fildes,/* __int64 */ offset,whence) +/* #define _TIFF_tell_f(fildes) /\* __int64 *\/ _telli64(fildes) */ +#define _TIFF_fseek_f(stream,offset,whence) _fseeki64(stream,/* __int64 */ offset,whence) +#define _TIFF_fstat_f(fildes,stat_buff) _fstati64(fildes,/* struct _stati64 */ stat_buff) +/* #define _TIFF_ftell_f(stream) /\* __int64 *\/ _ftelli64(stream) */ +/* #define _TIFF_stat_f(path,stat_buff) _stati64(path,/\* struct _stati64 *\/ stat_buff) */ +#define _TIFF_stat_s struct _stati64 +#define _TIFF_off_t __int64 +#else +typedef size_t TIFFIOSize_t; +#define _TIFF_lseek_f(fildes,offset,whence) lseek(fildes,offset,whence) +/* #define _TIFF_tell_f(fildes) (_TIFF_lseek_f(fildes,0,SEEK_CUR)) */ +#define _TIFF_fseek_f(stream,offset,whence) fseek(stream,offset,whence) +#define _TIFF_fstat_f(fildes,stat_buff) fstat(fildes,stat_buff) +/* #define _TIFF_ftell_f(stream) ftell(stream) */ +/* #define _TIFF_stat_f(path,stat_buff) stat(path,stat_buff) */ +#define _TIFF_stat_s struct stat +#define _TIFF_off_t off_t +#endif + +#if __clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ >= 8) +#define TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW __attribute__((no_sanitize("unsigned-integer-overflow"))) +#else +#define TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW +#endif + + #if defined(__cplusplus) extern "C" { #endif @@ -308,6 +371,20 @@ extern void* _TIFFCheckRealloc(TIFF*, void*, tmsize_t, tmsize_t, const char*); extern double _TIFFUInt64ToDouble(uint64); extern float _TIFFUInt64ToFloat(uint64); +extern tmsize_t +_TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, + void **buf, tmsize_t bufsizetoalloc, + tmsize_t size_to_read); +extern tmsize_t +_TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile, + void **buf, tmsize_t bufsizetoalloc, + tmsize_t size_to_read); +extern tmsize_t +_TIFFReadTileAndAllocBuffer(TIFF* tif, + void **buf, tmsize_t bufsizetoalloc, + uint32 x, uint32 y, uint32 z, uint16 s); +extern int _TIFFSeekOK(TIFF* tif, toff_t off); + extern int TIFFInitDumpMode(TIFF*, int); #ifdef PACKBITS_SUPPORT extern int TIFFInitPackBits(TIFF*, int); @@ -330,6 +407,7 @@ extern int TIFFInitOJPEG(TIFF*, int); #endif #ifdef JPEG_SUPPORT extern int TIFFInitJPEG(TIFF*, int); +extern int TIFFJPEGIsFullStripRequired(TIFF*); #endif #ifdef JBIG_SUPPORT extern int TIFFInitJBIG(TIFF*, int); diff --git a/3rdparty/libtiff/tiffvers.h b/3rdparty/libtiff/tiffvers.h index 38ee9fab34..7c415740f6 100644 --- a/3rdparty/libtiff/tiffvers.h +++ b/3rdparty/libtiff/tiffvers.h @@ -1,4 +1,4 @@ -#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.2\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." +#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.9\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." /* * This define can be used in code that requires * compilation-related definitions specific to a @@ -6,4 +6,4 @@ * version checking should be done based on the * string returned by TIFFGetVersion. */ -#define TIFFLIB_VERSION 20120615 +#define TIFFLIB_VERSION 20171118 diff --git a/3rdparty/libtiff/uvcode.h b/3rdparty/libtiff/uvcode.h index a147cd85d5..6286cfbb0c 100644 --- a/3rdparty/libtiff/uvcode.h +++ b/3rdparty/libtiff/uvcode.h @@ -3,173 +3,173 @@ #define UV_NDIVS 16289 #define UV_VSTART (float)0.016940 #define UV_NVS 163 -static struct { - float ustart; - short nus, ncum; +static const struct { + float ustart; + short nus, ncum; } uv_row[UV_NVS] = { - { (float)0.247663, 4, 0 }, - { (float)0.243779, 6, 4 }, - { (float)0.241684, 7, 10 }, - { (float)0.237874, 9, 17 }, - { (float)0.235906, 10, 26 }, - { (float)0.232153, 12, 36 }, - { (float)0.228352, 14, 48 }, - { (float)0.226259, 15, 62 }, - { (float)0.222371, 17, 77 }, - { (float)0.220410, 18, 94 }, - { (float)0.214710, 21, 112 }, - { (float)0.212714, 22, 133 }, - { (float)0.210721, 23, 155 }, - { (float)0.204976, 26, 178 }, - { (float)0.202986, 27, 204 }, - { (float)0.199245, 29, 231 }, - { (float)0.195525, 31, 260 }, - { (float)0.193560, 32, 291 }, - { (float)0.189878, 34, 323 }, - { (float)0.186216, 36, 357 }, - { (float)0.186216, 36, 393 }, - { (float)0.182592, 38, 429 }, - { (float)0.179003, 40, 467 }, - { (float)0.175466, 42, 507 }, - { (float)0.172001, 44, 549 }, - { (float)0.172001, 44, 593 }, - { (float)0.168612, 46, 637 }, - { (float)0.168612, 46, 683 }, - { (float)0.163575, 49, 729 }, - { (float)0.158642, 52, 778 }, - { (float)0.158642, 52, 830 }, - { (float)0.158642, 52, 882 }, - { (float)0.153815, 55, 934 }, - { (float)0.153815, 55, 989 }, - { (float)0.149097, 58, 1044 }, - { (float)0.149097, 58, 1102 }, - { (float)0.142746, 62, 1160 }, - { (float)0.142746, 62, 1222 }, - { (float)0.142746, 62, 1284 }, - { (float)0.138270, 65, 1346 }, - { (float)0.138270, 65, 1411 }, - { (float)0.138270, 65, 1476 }, - { (float)0.132166, 69, 1541 }, - { (float)0.132166, 69, 1610 }, - { (float)0.126204, 73, 1679 }, - { (float)0.126204, 73, 1752 }, - { (float)0.126204, 73, 1825 }, - { (float)0.120381, 77, 1898 }, - { (float)0.120381, 77, 1975 }, - { (float)0.120381, 77, 2052 }, - { (float)0.120381, 77, 2129 }, - { (float)0.112962, 82, 2206 }, - { (float)0.112962, 82, 2288 }, - { (float)0.112962, 82, 2370 }, - { (float)0.107450, 86, 2452 }, - { (float)0.107450, 86, 2538 }, - { (float)0.107450, 86, 2624 }, - { (float)0.107450, 86, 2710 }, - { (float)0.100343, 91, 2796 }, - { (float)0.100343, 91, 2887 }, - { (float)0.100343, 91, 2978 }, - { (float)0.095126, 95, 3069 }, - { (float)0.095126, 95, 3164 }, - { (float)0.095126, 95, 3259 }, - { (float)0.095126, 95, 3354 }, - { (float)0.088276, 100, 3449 }, - { (float)0.088276, 100, 3549 }, - { (float)0.088276, 100, 3649 }, - { (float)0.088276, 100, 3749 }, - { (float)0.081523, 105, 3849 }, - { (float)0.081523, 105, 3954 }, - { (float)0.081523, 105, 4059 }, - { (float)0.081523, 105, 4164 }, - { (float)0.074861, 110, 4269 }, - { (float)0.074861, 110, 4379 }, - { (float)0.074861, 110, 4489 }, - { (float)0.074861, 110, 4599 }, - { (float)0.068290, 115, 4709 }, - { (float)0.068290, 115, 4824 }, - { (float)0.068290, 115, 4939 }, - { (float)0.068290, 115, 5054 }, - { (float)0.063573, 119, 5169 }, - { (float)0.063573, 119, 5288 }, - { (float)0.063573, 119, 5407 }, - { (float)0.063573, 119, 5526 }, - { (float)0.057219, 124, 5645 }, - { (float)0.057219, 124, 5769 }, - { (float)0.057219, 124, 5893 }, - { (float)0.057219, 124, 6017 }, - { (float)0.050985, 129, 6141 }, - { (float)0.050985, 129, 6270 }, - { (float)0.050985, 129, 6399 }, - { (float)0.050985, 129, 6528 }, - { (float)0.050985, 129, 6657 }, - { (float)0.044859, 134, 6786 }, - { (float)0.044859, 134, 6920 }, - { (float)0.044859, 134, 7054 }, - { (float)0.044859, 134, 7188 }, - { (float)0.040571, 138, 7322 }, - { (float)0.040571, 138, 7460 }, - { (float)0.040571, 138, 7598 }, - { (float)0.040571, 138, 7736 }, - { (float)0.036339, 142, 7874 }, - { (float)0.036339, 142, 8016 }, - { (float)0.036339, 142, 8158 }, - { (float)0.036339, 142, 8300 }, - { (float)0.032139, 146, 8442 }, - { (float)0.032139, 146, 8588 }, - { (float)0.032139, 146, 8734 }, - { (float)0.032139, 146, 8880 }, - { (float)0.027947, 150, 9026 }, - { (float)0.027947, 150, 9176 }, - { (float)0.027947, 150, 9326 }, - { (float)0.023739, 154, 9476 }, - { (float)0.023739, 154, 9630 }, - { (float)0.023739, 154, 9784 }, - { (float)0.023739, 154, 9938 }, - { (float)0.019504, 158, 10092 }, - { (float)0.019504, 158, 10250 }, - { (float)0.019504, 158, 10408 }, - { (float)0.016976, 161, 10566 }, - { (float)0.016976, 161, 10727 }, - { (float)0.016976, 161, 10888 }, - { (float)0.016976, 161, 11049 }, - { (float)0.012639, 165, 11210 }, - { (float)0.012639, 165, 11375 }, - { (float)0.012639, 165, 11540 }, - { (float)0.009991, 168, 11705 }, - { (float)0.009991, 168, 11873 }, - { (float)0.009991, 168, 12041 }, - { (float)0.009016, 170, 12209 }, - { (float)0.009016, 170, 12379 }, - { (float)0.009016, 170, 12549 }, - { (float)0.006217, 173, 12719 }, - { (float)0.006217, 173, 12892 }, - { (float)0.005097, 175, 13065 }, - { (float)0.005097, 175, 13240 }, - { (float)0.005097, 175, 13415 }, - { (float)0.003909, 177, 13590 }, - { (float)0.003909, 177, 13767 }, - { (float)0.002340, 177, 13944 }, - { (float)0.002389, 170, 14121 }, - { (float)0.001068, 164, 14291 }, - { (float)0.001653, 157, 14455 }, - { (float)0.000717, 150, 14612 }, - { (float)0.001614, 143, 14762 }, - { (float)0.000270, 136, 14905 }, - { (float)0.000484, 129, 15041 }, - { (float)0.001103, 123, 15170 }, - { (float)0.001242, 115, 15293 }, - { (float)0.001188, 109, 15408 }, - { (float)0.001011, 103, 15517 }, - { (float)0.000709, 97, 15620 }, - { (float)0.000301, 89, 15717 }, - { (float)0.002416, 82, 15806 }, - { (float)0.003251, 76, 15888 }, - { (float)0.003246, 69, 15964 }, - { (float)0.004141, 62, 16033 }, - { (float)0.005963, 55, 16095 }, - { (float)0.008839, 47, 16150 }, - { (float)0.010490, 40, 16197 }, - { (float)0.016994, 31, 16237 }, - { (float)0.023659, 21, 16268 }, + { (float)0.247663, 4, 0 }, + { (float)0.243779, 6, 4 }, + { (float)0.241684, 7, 10 }, + { (float)0.237874, 9, 17 }, + { (float)0.235906, 10, 26 }, + { (float)0.232153, 12, 36 }, + { (float)0.228352, 14, 48 }, + { (float)0.226259, 15, 62 }, + { (float)0.222371, 17, 77 }, + { (float)0.220410, 18, 94 }, + { (float)0.214710, 21, 112 }, + { (float)0.212714, 22, 133 }, + { (float)0.210721, 23, 155 }, + { (float)0.204976, 26, 178 }, + { (float)0.202986, 27, 204 }, + { (float)0.199245, 29, 231 }, + { (float)0.195525, 31, 260 }, + { (float)0.193560, 32, 291 }, + { (float)0.189878, 34, 323 }, + { (float)0.186216, 36, 357 }, + { (float)0.186216, 36, 393 }, + { (float)0.182592, 38, 429 }, + { (float)0.179003, 40, 467 }, + { (float)0.175466, 42, 507 }, + { (float)0.172001, 44, 549 }, + { (float)0.172001, 44, 593 }, + { (float)0.168612, 46, 637 }, + { (float)0.168612, 46, 683 }, + { (float)0.163575, 49, 729 }, + { (float)0.158642, 52, 778 }, + { (float)0.158642, 52, 830 }, + { (float)0.158642, 52, 882 }, + { (float)0.153815, 55, 934 }, + { (float)0.153815, 55, 989 }, + { (float)0.149097, 58, 1044 }, + { (float)0.149097, 58, 1102 }, + { (float)0.142746, 62, 1160 }, + { (float)0.142746, 62, 1222 }, + { (float)0.142746, 62, 1284 }, + { (float)0.138270, 65, 1346 }, + { (float)0.138270, 65, 1411 }, + { (float)0.138270, 65, 1476 }, + { (float)0.132166, 69, 1541 }, + { (float)0.132166, 69, 1610 }, + { (float)0.126204, 73, 1679 }, + { (float)0.126204, 73, 1752 }, + { (float)0.126204, 73, 1825 }, + { (float)0.120381, 77, 1898 }, + { (float)0.120381, 77, 1975 }, + { (float)0.120381, 77, 2052 }, + { (float)0.120381, 77, 2129 }, + { (float)0.112962, 82, 2206 }, + { (float)0.112962, 82, 2288 }, + { (float)0.112962, 82, 2370 }, + { (float)0.107450, 86, 2452 }, + { (float)0.107450, 86, 2538 }, + { (float)0.107450, 86, 2624 }, + { (float)0.107450, 86, 2710 }, + { (float)0.100343, 91, 2796 }, + { (float)0.100343, 91, 2887 }, + { (float)0.100343, 91, 2978 }, + { (float)0.095126, 95, 3069 }, + { (float)0.095126, 95, 3164 }, + { (float)0.095126, 95, 3259 }, + { (float)0.095126, 95, 3354 }, + { (float)0.088276, 100, 3449 }, + { (float)0.088276, 100, 3549 }, + { (float)0.088276, 100, 3649 }, + { (float)0.088276, 100, 3749 }, + { (float)0.081523, 105, 3849 }, + { (float)0.081523, 105, 3954 }, + { (float)0.081523, 105, 4059 }, + { (float)0.081523, 105, 4164 }, + { (float)0.074861, 110, 4269 }, + { (float)0.074861, 110, 4379 }, + { (float)0.074861, 110, 4489 }, + { (float)0.074861, 110, 4599 }, + { (float)0.068290, 115, 4709 }, + { (float)0.068290, 115, 4824 }, + { (float)0.068290, 115, 4939 }, + { (float)0.068290, 115, 5054 }, + { (float)0.063573, 119, 5169 }, + { (float)0.063573, 119, 5288 }, + { (float)0.063573, 119, 5407 }, + { (float)0.063573, 119, 5526 }, + { (float)0.057219, 124, 5645 }, + { (float)0.057219, 124, 5769 }, + { (float)0.057219, 124, 5893 }, + { (float)0.057219, 124, 6017 }, + { (float)0.050985, 129, 6141 }, + { (float)0.050985, 129, 6270 }, + { (float)0.050985, 129, 6399 }, + { (float)0.050985, 129, 6528 }, + { (float)0.050985, 129, 6657 }, + { (float)0.044859, 134, 6786 }, + { (float)0.044859, 134, 6920 }, + { (float)0.044859, 134, 7054 }, + { (float)0.044859, 134, 7188 }, + { (float)0.040571, 138, 7322 }, + { (float)0.040571, 138, 7460 }, + { (float)0.040571, 138, 7598 }, + { (float)0.040571, 138, 7736 }, + { (float)0.036339, 142, 7874 }, + { (float)0.036339, 142, 8016 }, + { (float)0.036339, 142, 8158 }, + { (float)0.036339, 142, 8300 }, + { (float)0.032139, 146, 8442 }, + { (float)0.032139, 146, 8588 }, + { (float)0.032139, 146, 8734 }, + { (float)0.032139, 146, 8880 }, + { (float)0.027947, 150, 9026 }, + { (float)0.027947, 150, 9176 }, + { (float)0.027947, 150, 9326 }, + { (float)0.023739, 154, 9476 }, + { (float)0.023739, 154, 9630 }, + { (float)0.023739, 154, 9784 }, + { (float)0.023739, 154, 9938 }, + { (float)0.019504, 158, 10092 }, + { (float)0.019504, 158, 10250 }, + { (float)0.019504, 158, 10408 }, + { (float)0.016976, 161, 10566 }, + { (float)0.016976, 161, 10727 }, + { (float)0.016976, 161, 10888 }, + { (float)0.016976, 161, 11049 }, + { (float)0.012639, 165, 11210 }, + { (float)0.012639, 165, 11375 }, + { (float)0.012639, 165, 11540 }, + { (float)0.009991, 168, 11705 }, + { (float)0.009991, 168, 11873 }, + { (float)0.009991, 168, 12041 }, + { (float)0.009016, 170, 12209 }, + { (float)0.009016, 170, 12379 }, + { (float)0.009016, 170, 12549 }, + { (float)0.006217, 173, 12719 }, + { (float)0.006217, 173, 12892 }, + { (float)0.005097, 175, 13065 }, + { (float)0.005097, 175, 13240 }, + { (float)0.005097, 175, 13415 }, + { (float)0.003909, 177, 13590 }, + { (float)0.003909, 177, 13767 }, + { (float)0.002340, 177, 13944 }, + { (float)0.002389, 170, 14121 }, + { (float)0.001068, 164, 14291 }, + { (float)0.001653, 157, 14455 }, + { (float)0.000717, 150, 14612 }, + { (float)0.001614, 143, 14762 }, + { (float)0.000270, 136, 14905 }, + { (float)0.000484, 129, 15041 }, + { (float)0.001103, 123, 15170 }, + { (float)0.001242, 115, 15293 }, + { (float)0.001188, 109, 15408 }, + { (float)0.001011, 103, 15517 }, + { (float)0.000709, 97, 15620 }, + { (float)0.000301, 89, 15717 }, + { (float)0.002416, 82, 15806 }, + { (float)0.003251, 76, 15888 }, + { (float)0.003246, 69, 15964 }, + { (float)0.004141, 62, 16033 }, + { (float)0.005963, 55, 16095 }, + { (float)0.008839, 47, 16150 }, + { (float)0.010490, 40, 16197 }, + { (float)0.016994, 31, 16237 }, + { (float)0.023659, 21, 16268 }, }; /* * Local Variables: diff --git a/cmake/OpenCVFindLibsGrfmt.cmake b/cmake/OpenCVFindLibsGrfmt.cmake index 5682df6071..e96f29774e 100644 --- a/cmake/OpenCVFindLibsGrfmt.cmake +++ b/cmake/OpenCVFindLibsGrfmt.cmake @@ -26,7 +26,28 @@ if(NOT ZLIB_FOUND) ocv_parse_header2(ZLIB "${${ZLIB_LIBRARY}_SOURCE_DIR}/zlib.h" ZLIB_VERSION) endif() -# --- libtiff (optional, should be searched after zlib) --- +# --- libjpeg (optional) --- +if(WITH_JPEG) + if(BUILD_JPEG) + ocv_clear_vars(JPEG_FOUND) + else() + include(FindJPEG) + endif() + + if(NOT JPEG_FOUND) + ocv_clear_vars(JPEG_LIBRARY JPEG_LIBRARIES JPEG_INCLUDE_DIR) + + set(JPEG_LIBRARY libjpeg) + set(JPEG_LIBRARIES ${JPEG_LIBRARY}) + add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libjpeg") + set(JPEG_INCLUDE_DIR "${${JPEG_LIBRARY}_SOURCE_DIR}") + endif() + + ocv_parse_header("${JPEG_INCLUDE_DIR}/jpeglib.h" JPEG_VERSION_LINES JPEG_LIB_VERSION) + set(HAVE_JPEG YES) +endif() + +# --- libtiff (optional, should be searched after zlib and libjpeg) --- if(WITH_TIFF) if(BUILD_TIFF) ocv_clear_vars(TIFF_FOUND) @@ -68,27 +89,6 @@ if(WITH_TIFF) set(HAVE_TIFF YES) endif() -# --- libjpeg (optional) --- -if(WITH_JPEG) - if(BUILD_JPEG) - ocv_clear_vars(JPEG_FOUND) - else() - include(FindJPEG) - endif() - - if(NOT JPEG_FOUND) - ocv_clear_vars(JPEG_LIBRARY JPEG_LIBRARIES JPEG_INCLUDE_DIR) - - set(JPEG_LIBRARY libjpeg) - set(JPEG_LIBRARIES ${JPEG_LIBRARY}) - add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libjpeg") - set(JPEG_INCLUDE_DIR "${${JPEG_LIBRARY}_SOURCE_DIR}") - endif() - - ocv_parse_header("${JPEG_INCLUDE_DIR}/jpeglib.h" JPEG_VERSION_LINES JPEG_LIB_VERSION) - set(HAVE_JPEG YES) -endif() - # --- libwebp (optional) --- if(WITH_WEBP) From cd4176104d593528d0383b734f8d9f25f11b6d34 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Fri, 8 Dec 2017 18:19:30 +0300 Subject: [PATCH 8/8] 3rdparty: update libwebp 0.6.1 --- 3rdparty/libwebp/CMakeLists.txt | 15 +- 3rdparty/libwebp/dec/Makefile.am | 28 - 3rdparty/libwebp/demux/Makefile.am | 14 - 3rdparty/libwebp/demux/libwebpdemux.pc.in | 11 - 3rdparty/libwebp/demux/libwebpdemux.rc | 41 - 3rdparty/libwebp/dsp/Makefile.am | 153 -- 3rdparty/libwebp/enc/Makefile.am | 42 - .../libwebp/enc/backward_references_enc.c | 1800 ----------------- 3rdparty/libwebp/mux/Makefile.am | 19 - 3rdparty/libwebp/mux/libwebpmux.pc.in | 12 - 3rdparty/libwebp/mux/libwebpmux.rc | 41 - 3rdparty/libwebp/{ => src}/dec/alpha_dec.c | 14 +- 3rdparty/libwebp/{ => src}/dec/alphai_dec.h | 10 +- 3rdparty/libwebp/{ => src}/dec/buffer_dec.c | 51 +- 3rdparty/libwebp/{ => src}/dec/common_dec.h | 6 +- 3rdparty/libwebp/{ => src}/dec/frame_dec.c | 16 +- 3rdparty/libwebp/{ => src}/dec/idec_dec.c | 14 +- 3rdparty/libwebp/{ => src}/dec/io_dec.c | 24 +- 3rdparty/libwebp/{ => src}/dec/quant_dec.c | 2 +- 3rdparty/libwebp/{ => src}/dec/tree_dec.c | 18 +- 3rdparty/libwebp/{ => src}/dec/vp8_dec.c | 12 +- 3rdparty/libwebp/{ => src}/dec/vp8_dec.h | 18 +- 3rdparty/libwebp/{ => src}/dec/vp8i_dec.h | 21 +- 3rdparty/libwebp/{ => src}/dec/vp8l_dec.c | 54 +- 3rdparty/libwebp/{ => src}/dec/vp8li_dec.h | 14 +- 3rdparty/libwebp/{ => src}/dec/webp_dec.c | 14 +- 3rdparty/libwebp/{ => src}/dec/webpi_dec.h | 10 +- .../libwebp/{ => src}/demux/anim_decode.c | 8 +- 3rdparty/libwebp/{ => src}/demux/demux.c | 24 +- .../libwebp/{ => src}/dsp/alpha_processing.c | 114 +- .../dsp/alpha_processing_mips_dsp_r2.c | 55 +- .../{ => src}/dsp/alpha_processing_neon.c | 4 +- .../{ => src}/dsp/alpha_processing_sse2.c | 88 +- .../{ => src}/dsp/alpha_processing_sse41.c | 10 +- 3rdparty/libwebp/{ => src}/dsp/argb.c | 0 .../libwebp/{ => src}/dsp/argb_mips_dsp_r2.c | 0 3rdparty/libwebp/{ => src}/dsp/argb_sse2.c | 3 + 3rdparty/libwebp/{ => src}/dsp/common_sse2.h | 0 3rdparty/libwebp/{ => src}/dsp/cost.c | 14 +- 3rdparty/libwebp/{ => src}/dsp/cost_mips32.c | 14 +- .../libwebp/{ => src}/dsp/cost_mips_dsp_r2.c | 8 +- 3rdparty/libwebp/{ => src}/dsp/cost_sse2.c | 18 +- 3rdparty/libwebp/{ => src}/dsp/cpu.c | 4 +- 3rdparty/libwebp/{ => src}/dsp/dec.c | 391 ++-- .../libwebp/{ => src}/dsp/dec_clip_tables.c | 13 +- 3rdparty/libwebp/{ => src}/dsp/dec_mips32.c | 4 +- .../libwebp/{ => src}/dsp/dec_mips_dsp_r2.c | 4 +- 3rdparty/libwebp/{ => src}/dsp/dec_msa.c | 15 +- 3rdparty/libwebp/{ => src}/dsp/dec_neon.c | 715 +++---- 3rdparty/libwebp/{ => src}/dsp/dec_sse2.c | 456 +++-- 3rdparty/libwebp/{ => src}/dsp/dec_sse41.c | 10 +- 3rdparty/libwebp/{ => src}/dsp/dsp.h | 98 +- 3rdparty/libwebp/{ => src}/dsp/enc.c | 292 +-- 3rdparty/libwebp/{ => src}/dsp/enc_avx2.c | 2 +- 3rdparty/libwebp/{ => src}/dsp/enc_mips32.c | 77 +- .../libwebp/{ => src}/dsp/enc_mips_dsp_r2.c | 99 +- 3rdparty/libwebp/{ => src}/dsp/enc_msa.c | 114 +- 3rdparty/libwebp/{ => src}/dsp/enc_neon.c | 198 +- 3rdparty/libwebp/{ => src}/dsp/enc_sse2.c | 477 ++--- 3rdparty/libwebp/{ => src}/dsp/enc_sse41.c | 66 +- 3rdparty/libwebp/{ => src}/dsp/filters.c | 195 +- .../{ => src}/dsp/filters_mips_dsp_r2.c | 97 +- 3rdparty/libwebp/{ => src}/dsp/filters_msa.c | 22 +- 3rdparty/libwebp/{ => src}/dsp/filters_neon.c | 18 +- 3rdparty/libwebp/{ => src}/dsp/filters_sse2.c | 115 +- 3rdparty/libwebp/{ => src}/dsp/lossless.c | 199 +- 3rdparty/libwebp/{ => src}/dsp/lossless.h | 12 +- .../libwebp/{ => src}/dsp/lossless_common.h | 12 +- 3rdparty/libwebp/{ => src}/dsp/lossless_enc.c | 134 +- .../{ => src}/dsp/lossless_enc_mips32.c | 59 +- .../{ => src}/dsp/lossless_enc_mips_dsp_r2.c | 40 +- .../libwebp/{ => src}/dsp/lossless_enc_msa.c | 17 +- .../libwebp/{ => src}/dsp/lossless_enc_neon.c | 29 +- .../libwebp/{ => src}/dsp/lossless_enc_sse2.c | 93 +- .../{ => src}/dsp/lossless_enc_sse41.c | 9 +- .../{ => src}/dsp/lossless_mips_dsp_r2.c | 109 +- 3rdparty/libwebp/{ => src}/dsp/lossless_msa.c | 41 +- .../libwebp/{ => src}/dsp/lossless_neon.c | 63 +- .../libwebp/{ => src}/dsp/lossless_sse2.c | 271 +-- 3rdparty/libwebp/{ => src}/dsp/mips_macro.h | 0 3rdparty/libwebp/{ => src}/dsp/msa_macro.h | 2 + 3rdparty/libwebp/{ => src}/dsp/neon.h | 11 +- 3rdparty/libwebp/{ => src}/dsp/rescaler.c | 43 +- .../libwebp/{ => src}/dsp/rescaler_mips32.c | 24 +- .../{ => src}/dsp/rescaler_mips_dsp_r2.c | 14 +- 3rdparty/libwebp/{ => src}/dsp/rescaler_msa.c | 16 +- .../libwebp/{ => src}/dsp/rescaler_neon.c | 26 +- .../libwebp/{ => src}/dsp/rescaler_sse2.c | 90 +- 3rdparty/libwebp/src/dsp/ssim.c | 166 ++ 3rdparty/libwebp/src/dsp/ssim_sse2.c | 165 ++ 3rdparty/libwebp/{ => src}/dsp/upsampling.c | 161 +- .../{ => src}/dsp/upsampling_mips_dsp_r2.c | 47 +- .../libwebp/{ => src}/dsp/upsampling_msa.c | 50 +- .../libwebp/{ => src}/dsp/upsampling_neon.c | 52 +- .../libwebp/{ => src}/dsp/upsampling_sse2.c | 116 +- 3rdparty/libwebp/{ => src}/dsp/yuv.c | 98 +- 3rdparty/libwebp/{ => src}/dsp/yuv.h | 75 +- 3rdparty/libwebp/{ => src}/dsp/yuv_mips32.c | 20 +- .../libwebp/{ => src}/dsp/yuv_mips_dsp_r2.c | 20 +- 3rdparty/libwebp/src/dsp/yuv_neon.c | 288 +++ 3rdparty/libwebp/{ => src}/dsp/yuv_sse2.c | 367 ++-- 3rdparty/libwebp/{ => src}/enc/alpha_enc.c | 29 +- 3rdparty/libwebp/{ => src}/enc/analysis_enc.c | 6 +- .../src/enc/backward_references_cost_enc.c | 790 ++++++++ .../libwebp/src/enc/backward_references_enc.c | 943 +++++++++ .../{ => src}/enc/backward_references_enc.h | 57 +- 3rdparty/libwebp/{ => src}/enc/config_enc.c | 4 +- 3rdparty/libwebp/{ => src}/enc/cost_enc.c | 2 +- 3rdparty/libwebp/{ => src}/enc/cost_enc.h | 8 +- .../{ => src}/enc/delta_palettization_enc.c | 6 +- .../{ => src}/enc/delta_palettization_enc.h | 10 +- 3rdparty/libwebp/{ => src}/enc/filter_enc.c | 22 +- 3rdparty/libwebp/{ => src}/enc/frame_enc.c | 30 +- .../libwebp/{ => src}/enc/histogram_enc.c | 347 ++-- .../libwebp/{ => src}/enc/histogram_enc.h | 18 +- 3rdparty/libwebp/{ => src}/enc/iterator_enc.c | 2 +- .../libwebp/{ => src}/enc/near_lossless_enc.c | 73 +- .../libwebp/{ => src}/enc/picture_csp_enc.c | 109 +- 3rdparty/libwebp/{ => src}/enc/picture_enc.c | 27 +- .../libwebp/{ => src}/enc/picture_psnr_enc.c | 40 +- .../{ => src}/enc/picture_rescale_enc.c | 53 +- .../libwebp/{ => src}/enc/picture_tools_enc.c | 121 +- .../libwebp/{ => src}/enc/predictor_enc.c | 42 +- 3rdparty/libwebp/{ => src}/enc/quant_enc.c | 16 +- 3rdparty/libwebp/{ => src}/enc/syntax_enc.c | 14 +- 3rdparty/libwebp/{ => src}/enc/token_enc.c | 42 +- 3rdparty/libwebp/{ => src}/enc/tree_enc.c | 2 +- 3rdparty/libwebp/{ => src}/enc/vp8i_enc.h | 40 +- 3rdparty/libwebp/{ => src}/enc/vp8l_enc.c | 933 ++++++--- 3rdparty/libwebp/{ => src}/enc/vp8li_enc.h | 55 +- 3rdparty/libwebp/{ => src}/enc/webp_enc.c | 25 +- 3rdparty/libwebp/{ => src}/mux/anim_encode.c | 56 +- 3rdparty/libwebp/{ => src}/mux/animi.h | 2 +- 3rdparty/libwebp/{ => src}/mux/muxedit.c | 4 +- 3rdparty/libwebp/{ => src}/mux/muxi.h | 8 +- 3rdparty/libwebp/{ => src}/mux/muxinternal.c | 21 +- 3rdparty/libwebp/{ => src}/mux/muxread.c | 9 +- .../{ => src}/utils/bit_reader_inl_utils.h | 16 +- .../{ => src}/utils/bit_reader_utils.c | 6 +- .../{ => src}/utils/bit_reader_utils.h | 11 +- .../{ => src}/utils/bit_writer_utils.c | 33 +- .../{ => src}/utils/bit_writer_utils.h | 18 +- .../{ => src}/utils/color_cache_utils.c | 4 +- .../{ => src}/utils/color_cache_utils.h | 18 +- .../{ => src}/utils/endian_inl_utils.h | 12 +- .../libwebp/{ => src}/utils/filters_utils.c | 2 +- .../libwebp/{ => src}/utils/filters_utils.h | 10 +- .../{ => src}/utils/huffman_encode_utils.c | 6 +- .../{ => src}/utils/huffman_encode_utils.h | 8 +- .../libwebp/{ => src}/utils/huffman_utils.c | 6 +- .../libwebp/{ => src}/utils/huffman_utils.h | 10 +- .../{ => src}/utils/quant_levels_dec_utils.c | 9 +- .../{ => src}/utils/quant_levels_dec_utils.h | 8 +- .../{ => src}/utils/quant_levels_utils.c | 2 +- .../{ => src}/utils/quant_levels_utils.h | 8 +- .../libwebp/{ => src}/utils/random_utils.c | 2 +- .../libwebp/{ => src}/utils/random_utils.h | 8 +- .../libwebp/{ => src}/utils/rescaler_utils.c | 10 +- .../libwebp/{ => src}/utils/rescaler_utils.h | 8 +- .../libwebp/{ => src}/utils/thread_utils.c | 63 +- .../libwebp/{ => src}/utils/thread_utils.h | 19 +- 3rdparty/libwebp/{ => src}/utils/utils.c | 12 +- 3rdparty/libwebp/{ => src}/utils/utils.h | 34 +- 3rdparty/libwebp/{ => src}/webp/decode.h | 87 +- 3rdparty/libwebp/{ => src}/webp/demux.h | 67 +- 3rdparty/libwebp/{ => src}/webp/encode.h | 131 +- .../libwebp/{ => src}/webp/format_constants.h | 0 3rdparty/libwebp/{ => src}/webp/mux.h | 60 +- 3rdparty/libwebp/{ => src}/webp/mux_types.h | 0 3rdparty/libwebp/{ => src}/webp/types.h | 4 +- 3rdparty/libwebp/utils/Makefile.am | 50 - cmake/OpenCVFindLibsGrfmt.cmake | 2 +- 172 files changed, 7582 insertions(+), 6383 deletions(-) delete mode 100644 3rdparty/libwebp/dec/Makefile.am delete mode 100644 3rdparty/libwebp/demux/Makefile.am delete mode 100644 3rdparty/libwebp/demux/libwebpdemux.pc.in delete mode 100644 3rdparty/libwebp/demux/libwebpdemux.rc delete mode 100644 3rdparty/libwebp/dsp/Makefile.am delete mode 100644 3rdparty/libwebp/enc/Makefile.am delete mode 100644 3rdparty/libwebp/enc/backward_references_enc.c delete mode 100644 3rdparty/libwebp/mux/Makefile.am delete mode 100644 3rdparty/libwebp/mux/libwebpmux.pc.in delete mode 100644 3rdparty/libwebp/mux/libwebpmux.rc rename 3rdparty/libwebp/{ => src}/dec/alpha_dec.c (97%) rename 3rdparty/libwebp/{ => src}/dec/alphai_dec.h (89%) rename 3rdparty/libwebp/{ => src}/dec/buffer_dec.c (90%) rename 3rdparty/libwebp/{ => src}/dec/common_dec.h (94%) rename 3rdparty/libwebp/{ => src}/dec/frame_dec.c (98%) rename 3rdparty/libwebp/{ => src}/dec/idec_dec.c (99%) rename 3rdparty/libwebp/{ => src}/dec/io_dec.c (98%) rename 3rdparty/libwebp/{ => src}/dec/quant_dec.c (99%) rename 3rdparty/libwebp/{ => src}/dec/tree_dec.c (98%) rename 3rdparty/libwebp/{ => src}/dec/vp8_dec.c (99%) rename 3rdparty/libwebp/{ => src}/dec/vp8_dec.h (94%) rename 3rdparty/libwebp/{ => src}/dec/vp8i_dec.h (97%) rename 3rdparty/libwebp/{ => src}/dec/vp8l_dec.c (98%) rename 3rdparty/libwebp/{ => src}/dec/vp8li_dec.h (94%) rename 3rdparty/libwebp/{ => src}/dec/webp_dec.c (98%) rename 3rdparty/libwebp/{ => src}/dec/webpi_dec.h (97%) rename 3rdparty/libwebp/{ => src}/demux/anim_decode.c (99%) rename 3rdparty/libwebp/{ => src}/demux/demux.c (98%) rename 3rdparty/libwebp/{ => src}/dsp/alpha_processing.c (83%) rename 3rdparty/libwebp/{ => src}/dsp/alpha_processing_mips_dsp_r2.c (69%) rename 3rdparty/libwebp/{ => src}/dsp/alpha_processing_neon.c (99%) rename 3rdparty/libwebp/{ => src}/dsp/alpha_processing_sse2.c (76%) rename 3rdparty/libwebp/{ => src}/dsp/alpha_processing_sse41.c (93%) rename 3rdparty/libwebp/{ => src}/dsp/argb.c (100%) rename 3rdparty/libwebp/{ => src}/dsp/argb_mips_dsp_r2.c (100%) rename 3rdparty/libwebp/{ => src}/dsp/argb_sse2.c (94%) rename 3rdparty/libwebp/{ => src}/dsp/common_sse2.h (100%) rename 3rdparty/libwebp/{ => src}/dsp/cost.c (98%) rename 3rdparty/libwebp/{ => src}/dsp/cost_mips32.c (95%) rename 3rdparty/libwebp/{ => src}/dsp/cost_mips_dsp_r2.c (96%) rename 3rdparty/libwebp/{ => src}/dsp/cost_sse2.c (90%) rename 3rdparty/libwebp/{ => src}/dsp/cpu.c (98%) rename 3rdparty/libwebp/{ => src}/dsp/dec.c (62%) rename 3rdparty/libwebp/{ => src}/dsp/dec_clip_tables.c (99%) rename 3rdparty/libwebp/{ => src}/dsp/dec_mips32.c (99%) rename 3rdparty/libwebp/{ => src}/dsp/dec_mips_dsp_r2.c (99%) rename 3rdparty/libwebp/{ => src}/dsp/dec_msa.c (99%) rename 3rdparty/libwebp/{ => src}/dsp/dec_neon.c (71%) rename 3rdparty/libwebp/{ => src}/dsp/dec_sse2.c (73%) rename 3rdparty/libwebp/{ => src}/dsp/dec_sse41.c (87%) rename 3rdparty/libwebp/{ => src}/dsp/dsp.h (90%) rename 3rdparty/libwebp/{ => src}/dsp/enc.c (75%) rename 3rdparty/libwebp/{ => src}/dsp/enc_avx2.c (96%) rename 3rdparty/libwebp/{ => src}/dsp/enc_mips32.c (94%) rename 3rdparty/libwebp/{ => src}/dsp/enc_mips_dsp_r2.c (96%) rename 3rdparty/libwebp/{ => src}/dsp/enc_msa.c (91%) rename 3rdparty/libwebp/{ => src}/dsp/enc_neon.c (84%) rename 3rdparty/libwebp/{ => src}/dsp/enc_sse2.c (78%) rename 3rdparty/libwebp/{ => src}/dsp/enc_sse41.c (85%) rename 3rdparty/libwebp/{ => src}/dsp/filters.c (60%) rename 3rdparty/libwebp/{ => src}/dsp/filters_mips_dsp_r2.c (83%) rename 3rdparty/libwebp/{ => src}/dsp/filters_msa.c (88%) rename 3rdparty/libwebp/{ => src}/dsp/filters_neon.c (96%) rename 3rdparty/libwebp/{ => src}/dsp/filters_sse2.c (69%) rename 3rdparty/libwebp/{ => src}/dsp/lossless.c (79%) rename 3rdparty/libwebp/{ => src}/dsp/lossless.h (97%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_common.h (96%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_enc.c (90%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_enc_mips32.c (89%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_enc_mips_dsp_r2.c (89%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_enc_msa.c (92%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_enc_neon.c (82%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_enc_sse2.c (90%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_enc_sse41.c (86%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_mips_dsp_r2.c (91%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_msa.c (91%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_neon.c (92%) rename 3rdparty/libwebp/{ => src}/dsp/lossless_sse2.c (75%) rename 3rdparty/libwebp/{ => src}/dsp/mips_macro.h (100%) rename 3rdparty/libwebp/{ => src}/dsp/msa_macro.h (99%) rename 3rdparty/libwebp/{ => src}/dsp/neon.h (91%) rename 3rdparty/libwebp/{ => src}/dsp/rescaler.c (86%) rename 3rdparty/libwebp/{ => src}/dsp/rescaler_mips32.c (94%) rename 3rdparty/libwebp/{ => src}/dsp/rescaler_mips_dsp_r2.c (97%) rename 3rdparty/libwebp/{ => src}/dsp/rescaler_msa.c (97%) rename 3rdparty/libwebp/{ => src}/dsp/rescaler_neon.c (89%) rename 3rdparty/libwebp/{ => src}/dsp/rescaler_sse2.c (81%) create mode 100644 3rdparty/libwebp/src/dsp/ssim.c create mode 100644 3rdparty/libwebp/src/dsp/ssim_sse2.c rename 3rdparty/libwebp/{ => src}/dsp/upsampling.c (68%) rename 3rdparty/libwebp/{ => src}/dsp/upsampling_mips_dsp_r2.c (96%) rename 3rdparty/libwebp/{ => src}/dsp/upsampling_msa.c (97%) rename 3rdparty/libwebp/{ => src}/dsp/upsampling_neon.c (90%) rename 3rdparty/libwebp/{ => src}/dsp/upsampling_sse2.c (72%) rename 3rdparty/libwebp/{ => src}/dsp/yuv.c (82%) rename 3rdparty/libwebp/{ => src}/dsp/yuv.h (72%) rename 3rdparty/libwebp/{ => src}/dsp/yuv_mips32.c (92%) rename 3rdparty/libwebp/{ => src}/dsp/yuv_mips_dsp_r2.c (94%) create mode 100644 3rdparty/libwebp/src/dsp/yuv_neon.c rename 3rdparty/libwebp/{ => src}/dsp/yuv_sse2.c (70%) rename 3rdparty/libwebp/{ => src}/enc/alpha_enc.c (95%) rename 3rdparty/libwebp/{ => src}/enc/analysis_enc.c (99%) create mode 100644 3rdparty/libwebp/src/enc/backward_references_cost_enc.c create mode 100644 3rdparty/libwebp/src/enc/backward_references_enc.c rename 3rdparty/libwebp/{ => src}/enc/backward_references_enc.h (79%) rename 3rdparty/libwebp/{ => src}/enc/config_enc.c (98%) rename 3rdparty/libwebp/{ => src}/enc/cost_enc.c (99%) rename 3rdparty/libwebp/{ => src}/enc/cost_enc.h (95%) rename 3rdparty/libwebp/{ => src}/enc/delta_palettization_enc.c (99%) rename 3rdparty/libwebp/{ => src}/enc/delta_palettization_enc.h (81%) rename 3rdparty/libwebp/{ => src}/enc/filter_enc.c (95%) rename 3rdparty/libwebp/{ => src}/enc/frame_enc.c (97%) rename 3rdparty/libwebp/{ => src}/enc/histogram_enc.c (78%) rename 3rdparty/libwebp/{ => src}/enc/histogram_enc.h (90%) rename 3rdparty/libwebp/{ => src}/enc/iterator_enc.c (99%) rename 3rdparty/libwebp/{ => src}/enc/near_lossless_enc.c (58%) rename 3rdparty/libwebp/{ => src}/enc/picture_csp_enc.c (96%) rename 3rdparty/libwebp/{ => src}/enc/picture_enc.c (93%) rename 3rdparty/libwebp/{ => src}/enc/picture_psnr_enc.c (87%) rename 3rdparty/libwebp/{ => src}/enc/picture_rescale_enc.c (90%) rename 3rdparty/libwebp/{ => src}/enc/picture_tools_enc.c (64%) rename 3rdparty/libwebp/{ => src}/enc/predictor_enc.c (96%) rename 3rdparty/libwebp/{ => src}/enc/quant_enc.c (99%) rename 3rdparty/libwebp/{ => src}/enc/syntax_enc.c (97%) rename 3rdparty/libwebp/{ => src}/enc/token_enc.c (88%) rename 3rdparty/libwebp/{ => src}/enc/tree_enc.c (99%) rename 3rdparty/libwebp/{ => src}/enc/vp8i_enc.h (94%) rename 3rdparty/libwebp/{ => src}/enc/vp8l_enc.c (66%) rename 3rdparty/libwebp/{ => src}/enc/vp8li_enc.h (65%) rename 3rdparty/libwebp/{ => src}/enc/webp_enc.c (97%) rename 3rdparty/libwebp/{ => src}/mux/anim_encode.c (97%) rename 3rdparty/libwebp/{ => src}/mux/animi.h (98%) rename 3rdparty/libwebp/{ => src}/mux/muxedit.c (99%) rename 3rdparty/libwebp/{ => src}/mux/muxi.h (98%) rename 3rdparty/libwebp/{ => src}/mux/muxinternal.c (96%) rename 3rdparty/libwebp/{ => src}/mux/muxread.c (99%) rename 3rdparty/libwebp/{ => src}/utils/bit_reader_inl_utils.h (94%) rename 3rdparty/libwebp/{ => src}/utils/bit_reader_utils.c (98%) rename 3rdparty/libwebp/{ => src}/utils/bit_reader_utils.h (96%) rename 3rdparty/libwebp/{ => src}/utils/bit_writer_utils.c (91%) rename 3rdparty/libwebp/{ => src}/utils/bit_writer_utils.h (88%) rename 3rdparty/libwebp/{ => src}/utils/color_cache_utils.c (95%) rename 3rdparty/libwebp/{ => src}/utils/color_cache_utils.h (86%) rename 3rdparty/libwebp/{ => src}/utils/endian_inl_utils.h (93%) rename 3rdparty/libwebp/{ => src}/utils/filters_utils.c (98%) rename 3rdparty/libwebp/{ => src}/utils/filters_utils.h (83%) rename 3rdparty/libwebp/{ => src}/utils/huffman_encode_utils.c (99%) rename 3rdparty/libwebp/{ => src}/utils/huffman_encode_utils.h (92%) rename 3rdparty/libwebp/{ => src}/utils/huffman_utils.c (98%) rename 3rdparty/libwebp/{ => src}/utils/huffman_utils.h (94%) rename 3rdparty/libwebp/{ => src}/utils/quant_levels_dec_utils.c (97%) rename 3rdparty/libwebp/{ => src}/utils/quant_levels_dec_utils.h (86%) rename 3rdparty/libwebp/{ => src}/utils/quant_levels_utils.c (98%) rename 3rdparty/libwebp/{ => src}/utils/quant_levels_utils.h (86%) rename 3rdparty/libwebp/{ => src}/utils/random_utils.c (98%) rename 3rdparty/libwebp/{ => src}/utils/random_utils.h (93%) rename 3rdparty/libwebp/{ => src}/utils/rescaler_utils.c (95%) rename 3rdparty/libwebp/{ => src}/utils/rescaler_utils.h (96%) rename 3rdparty/libwebp/{ => src}/utils/thread_utils.c (86%) rename 3rdparty/libwebp/{ => src}/utils/thread_utils.h (89%) rename 3rdparty/libwebp/{ => src}/utils/utils.c (97%) rename 3rdparty/libwebp/{ => src}/utils/utils.h (86%) rename 3rdparty/libwebp/{ => src}/webp/decode.h (90%) rename 3rdparty/libwebp/{ => src}/webp/demux.h (85%) rename 3rdparty/libwebp/{ => src}/webp/encode.h (84%) rename 3rdparty/libwebp/{ => src}/webp/format_constants.h (100%) rename 3rdparty/libwebp/{ => src}/webp/mux.h (92%) rename 3rdparty/libwebp/{ => src}/webp/mux_types.h (100%) rename 3rdparty/libwebp/{ => src}/webp/types.h (92%) delete mode 100644 3rdparty/libwebp/utils/Makefile.am diff --git a/3rdparty/libwebp/CMakeLists.txt b/3rdparty/libwebp/CMakeLists.txt index 2aebc4cc33..a2e62bc13a 100644 --- a/3rdparty/libwebp/CMakeLists.txt +++ b/3rdparty/libwebp/CMakeLists.txt @@ -9,8 +9,8 @@ if(ANDROID) ocv_include_directories(${CPUFEATURES_INCLUDE_DIRS}) endif() -file(GLOB lib_srcs dec/*.c demux/*.c dsp/*.c enc/*.c mux/*.c utils/*.c webp/*.c) -file(GLOB lib_hdrs dec/*.h demux/*.h dsp/*.h enc/*.h mux/*.h utils/*.h webp/*.h) +file(GLOB lib_srcs src/dec/*.c src/demux/*.c src/dsp/*.c src/enc/*.c src/mux/*.c src/utils/*.c src/webp/*.c) +file(GLOB lib_hdrs src/dec/*.h src/demux/*.h src/dsp/*.h src/enc/*.h src/mux/*.h src/utils/*.h src/webp/*.h) # FIXIT if(ANDROID AND ARMEABI_V7A AND NOT NEON) @@ -34,13 +34,10 @@ if(ANDROID) target_link_libraries(${WEBP_LIBRARY} ${CPUFEATURES_LIBRARIES}) endif() -if(UNIX) - if(CMAKE_COMPILER_IS_GNUCXX OR CV_ICC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - endif() -endif() - -ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-variable -Wunused-function -Wshadow -Wmaybe-uninitialized) +ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-variable -Wunused-function -Wshadow -Wmaybe-uninitialized + -Wmissing-prototypes # clang + -Wmissing-declarations # gcc +) ocv_warnings_disable(CMAKE_C_FLAGS /wd4244 /wd4267) # vs2005 set_target_properties(${WEBP_LIBRARY} diff --git a/3rdparty/libwebp/dec/Makefile.am b/3rdparty/libwebp/dec/Makefile.am deleted file mode 100644 index 8919c42b23..0000000000 --- a/3rdparty/libwebp/dec/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -noinst_LTLIBRARIES = libwebpdecode.la - -libwebpdecode_la_SOURCES = -libwebpdecode_la_SOURCES += alpha_dec.c -libwebpdecode_la_SOURCES += alphai_dec.h -libwebpdecode_la_SOURCES += buffer_dec.c -libwebpdecode_la_SOURCES += common_dec.h -libwebpdecode_la_SOURCES += vp8_dec.h -libwebpdecode_la_SOURCES += frame_dec.c -libwebpdecode_la_SOURCES += idec_dec.c -libwebpdecode_la_SOURCES += io_dec.c -libwebpdecode_la_SOURCES += quant_dec.c -libwebpdecode_la_SOURCES += tree_dec.c -libwebpdecode_la_SOURCES += vp8_dec.c -libwebpdecode_la_SOURCES += vp8i_dec.h -libwebpdecode_la_SOURCES += vp8l_dec.c -libwebpdecode_la_SOURCES += vp8li_dec.h -libwebpdecode_la_SOURCES += webp_dec.c -libwebpdecode_la_SOURCES += webpi_dec.h - -libwebpdecodeinclude_HEADERS = -libwebpdecodeinclude_HEADERS += ../webp/decode.h -libwebpdecodeinclude_HEADERS += ../webp/types.h -noinst_HEADERS = -noinst_HEADERS += ../webp/format_constants.h - -libwebpdecode_la_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) -libwebpdecodeincludedir = $(includedir)/webp diff --git a/3rdparty/libwebp/demux/Makefile.am b/3rdparty/libwebp/demux/Makefile.am deleted file mode 100644 index c47536bb55..0000000000 --- a/3rdparty/libwebp/demux/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -lib_LTLIBRARIES = libwebpdemux.la - -libwebpdemux_la_SOURCES = -libwebpdemux_la_SOURCES += anim_decode.c demux.c - -libwebpdemuxinclude_HEADERS = -libwebpdemuxinclude_HEADERS += ../webp/demux.h -libwebpdemuxinclude_HEADERS += ../webp/mux_types.h -libwebpdemuxinclude_HEADERS += ../webp/types.h - -libwebpdemux_la_LIBADD = ../libwebp.la -libwebpdemux_la_LDFLAGS = -no-undefined -version-info 2:2:0 -libwebpdemuxincludedir = $(includedir)/webp -pkgconfig_DATA = libwebpdemux.pc diff --git a/3rdparty/libwebp/demux/libwebpdemux.pc.in b/3rdparty/libwebp/demux/libwebpdemux.pc.in deleted file mode 100644 index 6dfbbbdeee..0000000000 --- a/3rdparty/libwebp/demux/libwebpdemux.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libwebpdemux -Description: Library for parsing the WebP graphics format container -Version: @PACKAGE_VERSION@ -Requires: libwebp >= 0.2.0 -Cflags: -I${includedir} -Libs: -L${libdir} -lwebpdemux diff --git a/3rdparty/libwebp/demux/libwebpdemux.rc b/3rdparty/libwebp/demux/libwebpdemux.rc deleted file mode 100644 index b9ab68b3c2..0000000000 --- a/3rdparty/libwebp/demux/libwebpdemux.rc +++ /dev/null @@ -1,41 +0,0 @@ -#define APSTUDIO_READONLY_SYMBOLS -#include "winres.h" -#undef APSTUDIO_READONLY_SYMBOLS - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,3,0,2 - PRODUCTVERSION 0,3,0,2 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", "Google, Inc." - VALUE "FileDescription", "libwebpdemux DLL" - VALUE "FileVersion", "0.3.2" - VALUE "InternalName", "libwebpdemux.dll" - VALUE "LegalCopyright", "Copyright (C) 2017" - VALUE "OriginalFilename", "libwebpdemux.dll" - VALUE "ProductName", "WebP Image Demuxer" - VALUE "ProductVersion", "0.3.2" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // English (United States) resources diff --git a/3rdparty/libwebp/dsp/Makefile.am b/3rdparty/libwebp/dsp/Makefile.am deleted file mode 100644 index 33fc1e42ef..0000000000 --- a/3rdparty/libwebp/dsp/Makefile.am +++ /dev/null @@ -1,153 +0,0 @@ -noinst_LTLIBRARIES = libwebpdsp.la libwebpdsp_avx2.la -noinst_LTLIBRARIES += libwebpdsp_sse2.la libwebpdspdecode_sse2.la -noinst_LTLIBRARIES += libwebpdsp_sse41.la libwebpdspdecode_sse41.la -noinst_LTLIBRARIES += libwebpdsp_neon.la libwebpdspdecode_neon.la -noinst_LTLIBRARIES += libwebpdsp_msa.la libwebpdspdecode_msa.la - -if BUILD_LIBWEBPDECODER - noinst_LTLIBRARIES += libwebpdspdecode.la -endif - -common_HEADERS = ../webp/types.h -commondir = $(includedir)/webp - -COMMON_SOURCES = -COMMON_SOURCES += alpha_processing.c -COMMON_SOURCES += alpha_processing_mips_dsp_r2.c -COMMON_SOURCES += common_sse2.h -COMMON_SOURCES += cpu.c -COMMON_SOURCES += dec.c -COMMON_SOURCES += dec_clip_tables.c -COMMON_SOURCES += dec_mips32.c -COMMON_SOURCES += dec_mips_dsp_r2.c -COMMON_SOURCES += dsp.h -COMMON_SOURCES += filters.c -COMMON_SOURCES += filters_mips_dsp_r2.c -COMMON_SOURCES += lossless.c -COMMON_SOURCES += lossless.h -COMMON_SOURCES += lossless_common.h -COMMON_SOURCES += lossless_mips_dsp_r2.c -COMMON_SOURCES += mips_macro.h -COMMON_SOURCES += rescaler.c -COMMON_SOURCES += rescaler_mips32.c -COMMON_SOURCES += rescaler_mips_dsp_r2.c -COMMON_SOURCES += upsampling.c -COMMON_SOURCES += upsampling_mips_dsp_r2.c -COMMON_SOURCES += yuv.c -COMMON_SOURCES += yuv.h -COMMON_SOURCES += yuv_mips32.c -COMMON_SOURCES += yuv_mips_dsp_r2.c - -ENC_SOURCES = -ENC_SOURCES += argb.c -ENC_SOURCES += argb_mips_dsp_r2.c -ENC_SOURCES += cost.c -ENC_SOURCES += cost_mips32.c -ENC_SOURCES += cost_mips_dsp_r2.c -ENC_SOURCES += enc.c -ENC_SOURCES += enc_mips32.c -ENC_SOURCES += enc_mips_dsp_r2.c -ENC_SOURCES += lossless_enc.c -ENC_SOURCES += lossless_enc_mips32.c -ENC_SOURCES += lossless_enc_mips_dsp_r2.c - -libwebpdsp_avx2_la_SOURCES = -libwebpdsp_avx2_la_SOURCES += enc_avx2.c -libwebpdsp_avx2_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) -libwebpdsp_avx2_la_CFLAGS = $(AM_CFLAGS) $(AVX2_FLAGS) - -libwebpdspdecode_sse41_la_SOURCES = -libwebpdspdecode_sse41_la_SOURCES += alpha_processing_sse41.c -libwebpdspdecode_sse41_la_SOURCES += dec_sse41.c -libwebpdspdecode_sse41_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) -libwebpdspdecode_sse41_la_CFLAGS = $(AM_CFLAGS) $(SSE41_FLAGS) - -libwebpdspdecode_sse2_la_SOURCES = -libwebpdspdecode_sse2_la_SOURCES += alpha_processing_sse2.c -libwebpdspdecode_sse2_la_SOURCES += dec_sse2.c -libwebpdspdecode_sse2_la_SOURCES += filters_sse2.c -libwebpdspdecode_sse2_la_SOURCES += lossless_sse2.c -libwebpdspdecode_sse2_la_SOURCES += rescaler_sse2.c -libwebpdspdecode_sse2_la_SOURCES += upsampling_sse2.c -libwebpdspdecode_sse2_la_SOURCES += yuv_sse2.c -libwebpdspdecode_sse2_la_CPPFLAGS = $(libwebpdsp_sse2_la_CPPFLAGS) -libwebpdspdecode_sse2_la_CFLAGS = $(libwebpdsp_sse2_la_CFLAGS) - -libwebpdspdecode_neon_la_SOURCES = -libwebpdspdecode_neon_la_SOURCES += alpha_processing_neon.c -libwebpdspdecode_neon_la_SOURCES += dec_neon.c -libwebpdspdecode_neon_la_SOURCES += filters_neon.c -libwebpdspdecode_neon_la_SOURCES += lossless_neon.c -libwebpdspdecode_neon_la_SOURCES += neon.h -libwebpdspdecode_neon_la_SOURCES += rescaler_neon.c -libwebpdspdecode_neon_la_SOURCES += upsampling_neon.c -libwebpdspdecode_neon_la_CPPFLAGS = $(libwebpdsp_neon_la_CPPFLAGS) -libwebpdspdecode_neon_la_CFLAGS = $(libwebpdsp_neon_la_CFLAGS) - -libwebpdspdecode_msa_la_SOURCES = -libwebpdspdecode_msa_la_SOURCES += dec_msa.c -libwebpdspdecode_msa_la_SOURCES += filters_msa.c -libwebpdspdecode_msa_la_SOURCES += lossless_msa.c -libwebpdspdecode_msa_la_SOURCES += msa_macro.h -libwebpdspdecode_msa_la_SOURCES += rescaler_msa.c -libwebpdspdecode_msa_la_SOURCES += upsampling_msa.c -libwebpdspdecode_msa_la_CPPFLAGS = $(libwebpdsp_msa_la_CPPFLAGS) -libwebpdspdecode_msa_la_CFLAGS = $(libwebpdsp_msa_la_CFLAGS) - -libwebpdsp_sse2_la_SOURCES = -libwebpdsp_sse2_la_SOURCES += argb_sse2.c -libwebpdsp_sse2_la_SOURCES += cost_sse2.c -libwebpdsp_sse2_la_SOURCES += enc_sse2.c -libwebpdsp_sse2_la_SOURCES += lossless_enc_sse2.c -libwebpdsp_sse2_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) -libwebpdsp_sse2_la_CFLAGS = $(AM_CFLAGS) $(SSE2_FLAGS) -libwebpdsp_sse2_la_LIBADD = libwebpdspdecode_sse2.la - -libwebpdsp_sse41_la_SOURCES = -libwebpdsp_sse41_la_SOURCES += enc_sse41.c -libwebpdsp_sse41_la_SOURCES += lossless_enc_sse41.c -libwebpdsp_sse41_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) -libwebpdsp_sse41_la_CFLAGS = $(AM_CFLAGS) $(SSE41_FLAGS) -libwebpdsp_sse41_la_LIBADD = libwebpdspdecode_sse41.la - -libwebpdsp_neon_la_SOURCES = -libwebpdsp_neon_la_SOURCES += enc_neon.c -libwebpdsp_neon_la_SOURCES += lossless_enc_neon.c -libwebpdsp_neon_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) -libwebpdsp_neon_la_CFLAGS = $(AM_CFLAGS) $(NEON_FLAGS) -libwebpdsp_neon_la_LIBADD = libwebpdspdecode_neon.la - -libwebpdsp_msa_la_SOURCES = -libwebpdsp_msa_la_SOURCES += enc_msa.c -libwebpdsp_msa_la_SOURCES += lossless_enc_msa.c -libwebpdsp_msa_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) -libwebpdsp_msa_la_CFLAGS = $(AM_CFLAGS) -libwebpdsp_msa_la_LIBADD = libwebpdspdecode_msa.la - -libwebpdsp_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES) - -noinst_HEADERS = -noinst_HEADERS += ../dec/vp8_dec.h -noinst_HEADERS += ../webp/decode.h - -libwebpdsp_la_CPPFLAGS = -libwebpdsp_la_CPPFLAGS += $(AM_CPPFLAGS) -libwebpdsp_la_CPPFLAGS += $(USE_EXPERIMENTAL_CODE) $(USE_SWAP_16BIT_CSP) -libwebpdsp_la_LDFLAGS = -lm -libwebpdsp_la_LIBADD = -libwebpdsp_la_LIBADD += libwebpdsp_avx2.la libwebpdsp_sse2.la -libwebpdsp_la_LIBADD += libwebpdsp_sse41.la -libwebpdsp_la_LIBADD += libwebpdsp_neon.la -libwebpdsp_la_LIBADD += libwebpdsp_msa.la - -if BUILD_LIBWEBPDECODER - libwebpdspdecode_la_SOURCES = $(COMMON_SOURCES) - - libwebpdspdecode_la_CPPFLAGS = $(libwebpdsp_la_CPPFLAGS) - libwebpdspdecode_la_LDFLAGS = $(libwebpdsp_la_LDFLAGS) - libwebpdspdecode_la_LIBADD = - libwebpdspdecode_la_LIBADD += libwebpdspdecode_sse2.la - libwebpdspdecode_la_LIBADD += libwebpdspdecode_sse41.la - libwebpdspdecode_la_LIBADD += libwebpdspdecode_neon.la - libwebpdspdecode_la_LIBADD += libwebpdspdecode_msa.la -endif diff --git a/3rdparty/libwebp/enc/Makefile.am b/3rdparty/libwebp/enc/Makefile.am deleted file mode 100644 index aead7fec95..0000000000 --- a/3rdparty/libwebp/enc/Makefile.am +++ /dev/null @@ -1,42 +0,0 @@ -noinst_LTLIBRARIES = libwebpencode.la - -libwebpencode_la_SOURCES = -libwebpencode_la_SOURCES += alpha_enc.c -libwebpencode_la_SOURCES += analysis_enc.c -libwebpencode_la_SOURCES += backward_references_enc.c -libwebpencode_la_SOURCES += backward_references_enc.h -libwebpencode_la_SOURCES += config_enc.c -libwebpencode_la_SOURCES += cost_enc.c -libwebpencode_la_SOURCES += cost_enc.h -libwebpencode_la_SOURCES += delta_palettization_enc.c -libwebpencode_la_SOURCES += delta_palettization_enc.h -libwebpencode_la_SOURCES += filter_enc.c -libwebpencode_la_SOURCES += frame_enc.c -libwebpencode_la_SOURCES += histogram_enc.c -libwebpencode_la_SOURCES += histogram_enc.h -libwebpencode_la_SOURCES += iterator_enc.c -libwebpencode_la_SOURCES += near_lossless_enc.c -libwebpencode_la_SOURCES += picture_enc.c -libwebpencode_la_SOURCES += picture_csp_enc.c -libwebpencode_la_SOURCES += picture_psnr_enc.c -libwebpencode_la_SOURCES += picture_rescale_enc.c -libwebpencode_la_SOURCES += picture_tools_enc.c -libwebpencode_la_SOURCES += predictor_enc.c -libwebpencode_la_SOURCES += quant_enc.c -libwebpencode_la_SOURCES += syntax_enc.c -libwebpencode_la_SOURCES += token_enc.c -libwebpencode_la_SOURCES += tree_enc.c -libwebpencode_la_SOURCES += vp8i_enc.h -libwebpencode_la_SOURCES += vp8l_enc.c -libwebpencode_la_SOURCES += vp8li_enc.h -libwebpencode_la_SOURCES += webp_enc.c - -libwebpencodeinclude_HEADERS = -libwebpencodeinclude_HEADERS += ../webp/encode.h -libwebpencodeinclude_HEADERS += ../webp/types.h -noinst_HEADERS = -noinst_HEADERS += ../webp/format_constants.h - -libwebpencode_la_LDFLAGS = -lm -libwebpencode_la_CPPFLAGS = $(AM_CPPFLAGS) $(USE_EXPERIMENTAL_CODE) -libwebpencodeincludedir = $(includedir)/webp diff --git a/3rdparty/libwebp/enc/backward_references_enc.c b/3rdparty/libwebp/enc/backward_references_enc.c deleted file mode 100644 index 7c0559ff1e..0000000000 --- a/3rdparty/libwebp/enc/backward_references_enc.c +++ /dev/null @@ -1,1800 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. -// -// Use of this source code is governed by a BSD-style license -// that can be found in the COPYING file in the root of the source -// tree. An additional intellectual property rights grant can be found -// in the file PATENTS. All contributing project authors may -// be found in the AUTHORS file in the root of the source tree. -// ----------------------------------------------------------------------------- -// -// Author: Jyrki Alakuijala (jyrki@google.com) -// - -#include -#include - -#include "./backward_references_enc.h" -#include "./histogram_enc.h" -#include "../dsp/lossless.h" -#include "../dsp/lossless_common.h" -#include "../dsp/dsp.h" -#include "../utils/color_cache_utils.h" -#include "../utils/utils.h" - -#define VALUES_IN_BYTE 256 - -#define MIN_BLOCK_SIZE 256 // minimum block size for backward references - -#define MAX_ENTROPY (1e30f) - -// 1M window (4M bytes) minus 120 special codes for short distances. -#define WINDOW_SIZE_BITS 20 -#define WINDOW_SIZE ((1 << WINDOW_SIZE_BITS) - 120) - -// Minimum number of pixels for which it is cheaper to encode a -// distance + length instead of each pixel as a literal. -#define MIN_LENGTH 4 -// If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it -// is used in VP8LHashChain. -#define MAX_LENGTH_BITS 12 -// We want the max value to be attainable and stored in MAX_LENGTH_BITS bits. -#define MAX_LENGTH ((1 << MAX_LENGTH_BITS) - 1) -#if MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32 -#error "MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32" -#endif - -// ----------------------------------------------------------------------------- - -static const uint8_t plane_to_code_lut[128] = { - 96, 73, 55, 39, 23, 13, 5, 1, 255, 255, 255, 255, 255, 255, 255, 255, - 101, 78, 58, 42, 26, 16, 8, 2, 0, 3, 9, 17, 27, 43, 59, 79, - 102, 86, 62, 46, 32, 20, 10, 6, 4, 7, 11, 21, 33, 47, 63, 87, - 105, 90, 70, 52, 37, 28, 18, 14, 12, 15, 19, 29, 38, 53, 71, 91, - 110, 99, 82, 66, 48, 35, 30, 24, 22, 25, 31, 36, 49, 67, 83, 100, - 115, 108, 94, 76, 64, 50, 44, 40, 34, 41, 45, 51, 65, 77, 95, 109, - 118, 113, 103, 92, 80, 68, 60, 56, 54, 57, 61, 69, 81, 93, 104, 114, - 119, 116, 111, 106, 97, 88, 84, 74, 72, 75, 85, 89, 98, 107, 112, 117 -}; - -static int DistanceToPlaneCode(int xsize, int dist) { - const int yoffset = dist / xsize; - const int xoffset = dist - yoffset * xsize; - if (xoffset <= 8 && yoffset < 8) { - return plane_to_code_lut[yoffset * 16 + 8 - xoffset] + 1; - } else if (xoffset > xsize - 8 && yoffset < 7) { - return plane_to_code_lut[(yoffset + 1) * 16 + 8 + (xsize - xoffset)] + 1; - } - return dist + 120; -} - -// Returns the exact index where array1 and array2 are different. For an index -// inferior or equal to best_len_match, the return value just has to be strictly -// inferior to best_len_match. The current behavior is to return 0 if this index -// is best_len_match, and the index itself otherwise. -// If no two elements are the same, it returns max_limit. -static WEBP_INLINE int FindMatchLength(const uint32_t* const array1, - const uint32_t* const array2, - int best_len_match, int max_limit) { - // Before 'expensive' linear match, check if the two arrays match at the - // current best length index. - if (array1[best_len_match] != array2[best_len_match]) return 0; - - return VP8LVectorMismatch(array1, array2, max_limit); -} - -// ----------------------------------------------------------------------------- -// VP8LBackwardRefs - -struct PixOrCopyBlock { - PixOrCopyBlock* next_; // next block (or NULL) - PixOrCopy* start_; // data start - int size_; // currently used size -}; - -static void ClearBackwardRefs(VP8LBackwardRefs* const refs) { - assert(refs != NULL); - if (refs->tail_ != NULL) { - *refs->tail_ = refs->free_blocks_; // recycle all blocks at once - } - refs->free_blocks_ = refs->refs_; - refs->tail_ = &refs->refs_; - refs->last_block_ = NULL; - refs->refs_ = NULL; -} - -void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs) { - assert(refs != NULL); - ClearBackwardRefs(refs); - while (refs->free_blocks_ != NULL) { - PixOrCopyBlock* const next = refs->free_blocks_->next_; - WebPSafeFree(refs->free_blocks_); - refs->free_blocks_ = next; - } -} - -void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) { - assert(refs != NULL); - memset(refs, 0, sizeof(*refs)); - refs->tail_ = &refs->refs_; - refs->block_size_ = - (block_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : block_size; -} - -VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs) { - VP8LRefsCursor c; - c.cur_block_ = refs->refs_; - if (refs->refs_ != NULL) { - c.cur_pos = c.cur_block_->start_; - c.last_pos_ = c.cur_pos + c.cur_block_->size_; - } else { - c.cur_pos = NULL; - c.last_pos_ = NULL; - } - return c; -} - -void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c) { - PixOrCopyBlock* const b = c->cur_block_->next_; - c->cur_pos = (b == NULL) ? NULL : b->start_; - c->last_pos_ = (b == NULL) ? NULL : b->start_ + b->size_; - c->cur_block_ = b; -} - -// Create a new block, either from the free list or allocated -static PixOrCopyBlock* BackwardRefsNewBlock(VP8LBackwardRefs* const refs) { - PixOrCopyBlock* b = refs->free_blocks_; - if (b == NULL) { // allocate new memory chunk - const size_t total_size = - sizeof(*b) + refs->block_size_ * sizeof(*b->start_); - b = (PixOrCopyBlock*)WebPSafeMalloc(1ULL, total_size); - if (b == NULL) { - refs->error_ |= 1; - return NULL; - } - b->start_ = (PixOrCopy*)((uint8_t*)b + sizeof(*b)); // not always aligned - } else { // recycle from free-list - refs->free_blocks_ = b->next_; - } - *refs->tail_ = b; - refs->tail_ = &b->next_; - refs->last_block_ = b; - b->next_ = NULL; - b->size_ = 0; - return b; -} - -static WEBP_INLINE void BackwardRefsCursorAdd(VP8LBackwardRefs* const refs, - const PixOrCopy v) { - PixOrCopyBlock* b = refs->last_block_; - if (b == NULL || b->size_ == refs->block_size_) { - b = BackwardRefsNewBlock(refs); - if (b == NULL) return; // refs->error_ is set - } - b->start_[b->size_++] = v; -} - -int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src, - VP8LBackwardRefs* const dst) { - const PixOrCopyBlock* b = src->refs_; - ClearBackwardRefs(dst); - assert(src->block_size_ == dst->block_size_); - while (b != NULL) { - PixOrCopyBlock* const new_b = BackwardRefsNewBlock(dst); - if (new_b == NULL) return 0; // dst->error_ is set - memcpy(new_b->start_, b->start_, b->size_ * sizeof(*b->start_)); - new_b->size_ = b->size_; - b = b->next_; - } - return 1; -} - -// ----------------------------------------------------------------------------- -// Hash chains - -int VP8LHashChainInit(VP8LHashChain* const p, int size) { - assert(p->size_ == 0); - assert(p->offset_length_ == NULL); - assert(size > 0); - p->offset_length_ = - (uint32_t*)WebPSafeMalloc(size, sizeof(*p->offset_length_)); - if (p->offset_length_ == NULL) return 0; - p->size_ = size; - - return 1; -} - -void VP8LHashChainClear(VP8LHashChain* const p) { - assert(p != NULL); - WebPSafeFree(p->offset_length_); - - p->size_ = 0; - p->offset_length_ = NULL; -} - -// ----------------------------------------------------------------------------- - -#define HASH_MULTIPLIER_HI (0xc6a4a793ULL) -#define HASH_MULTIPLIER_LO (0x5bd1e996ULL) - -static WEBP_INLINE uint32_t GetPixPairHash64(const uint32_t* const argb) { - uint32_t key; - key = (argb[1] * HASH_MULTIPLIER_HI) & 0xffffffffu; - key += (argb[0] * HASH_MULTIPLIER_LO) & 0xffffffffu; - key = key >> (32 - HASH_BITS); - return key; -} - -// Returns the maximum number of hash chain lookups to do for a -// given compression quality. Return value in range [8, 86]. -static int GetMaxItersForQuality(int quality) { - return 8 + (quality * quality) / 128; -} - -static int GetWindowSizeForHashChain(int quality, int xsize) { - const int max_window_size = (quality > 75) ? WINDOW_SIZE - : (quality > 50) ? (xsize << 8) - : (quality > 25) ? (xsize << 6) - : (xsize << 4); - assert(xsize > 0); - return (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE : max_window_size; -} - -static WEBP_INLINE int MaxFindCopyLength(int len) { - return (len < MAX_LENGTH) ? len : MAX_LENGTH; -} - -int VP8LHashChainFill(VP8LHashChain* const p, int quality, - const uint32_t* const argb, int xsize, int ysize, - int low_effort) { - const int size = xsize * ysize; - const int iter_max = GetMaxItersForQuality(quality); - const uint32_t window_size = GetWindowSizeForHashChain(quality, xsize); - int pos; - int argb_comp; - uint32_t base_position; - int32_t* hash_to_first_index; - // Temporarily use the p->offset_length_ as a hash chain. - int32_t* chain = (int32_t*)p->offset_length_; - assert(size > 0); - assert(p->size_ != 0); - assert(p->offset_length_ != NULL); - - if (size <= 2) { - p->offset_length_[0] = p->offset_length_[size - 1] = 0; - return 1; - } - - hash_to_first_index = - (int32_t*)WebPSafeMalloc(HASH_SIZE, sizeof(*hash_to_first_index)); - if (hash_to_first_index == NULL) return 0; - - // Set the int32_t array to -1. - memset(hash_to_first_index, 0xff, HASH_SIZE * sizeof(*hash_to_first_index)); - // Fill the chain linking pixels with the same hash. - argb_comp = (argb[0] == argb[1]); - for (pos = 0; pos < size - 2;) { - uint32_t hash_code; - const int argb_comp_next = (argb[pos + 1] == argb[pos + 2]); - if (argb_comp && argb_comp_next) { - // Consecutive pixels with the same color will share the same hash. - // We therefore use a different hash: the color and its repetition - // length. - uint32_t tmp[2]; - uint32_t len = 1; - tmp[0] = argb[pos]; - // Figure out how far the pixels are the same. - // The last pixel has a different 64 bit hash, as its next pixel does - // not have the same color, so we just need to get to the last pixel equal - // to its follower. - while (pos + (int)len + 2 < size && argb[pos + len + 2] == argb[pos]) { - ++len; - } - if (len > MAX_LENGTH) { - // Skip the pixels that match for distance=1 and length>MAX_LENGTH - // because they are linked to their predecessor and we automatically - // check that in the main for loop below. Skipping means setting no - // predecessor in the chain, hence -1. - memset(chain + pos, 0xff, (len - MAX_LENGTH) * sizeof(*chain)); - pos += len - MAX_LENGTH; - len = MAX_LENGTH; - } - // Process the rest of the hash chain. - while (len) { - tmp[1] = len--; - hash_code = GetPixPairHash64(tmp); - chain[pos] = hash_to_first_index[hash_code]; - hash_to_first_index[hash_code] = pos++; - } - argb_comp = 0; - } else { - // Just move one pixel forward. - hash_code = GetPixPairHash64(argb + pos); - chain[pos] = hash_to_first_index[hash_code]; - hash_to_first_index[hash_code] = pos++; - argb_comp = argb_comp_next; - } - } - // Process the penultimate pixel. - chain[pos] = hash_to_first_index[GetPixPairHash64(argb + pos)]; - - WebPSafeFree(hash_to_first_index); - - // Find the best match interval at each pixel, defined by an offset to the - // pixel and a length. The right-most pixel cannot match anything to the right - // (hence a best length of 0) and the left-most pixel nothing to the left - // (hence an offset of 0). - assert(size > 2); - p->offset_length_[0] = p->offset_length_[size - 1] = 0; - for (base_position = size - 2; base_position > 0;) { - const int max_len = MaxFindCopyLength(size - 1 - base_position); - const uint32_t* const argb_start = argb + base_position; - int iter = iter_max; - int best_length = 0; - uint32_t best_distance = 0; - uint32_t best_argb; - const int min_pos = - (base_position > window_size) ? base_position - window_size : 0; - const int length_max = (max_len < 256) ? max_len : 256; - uint32_t max_base_position; - - pos = chain[base_position]; - if (!low_effort) { - int curr_length; - // Heuristic: use the comparison with the above line as an initialization. - if (base_position >= (uint32_t)xsize) { - curr_length = FindMatchLength(argb_start - xsize, argb_start, - best_length, max_len); - if (curr_length > best_length) { - best_length = curr_length; - best_distance = xsize; - } - --iter; - } - // Heuristic: compare to the previous pixel. - curr_length = - FindMatchLength(argb_start - 1, argb_start, best_length, max_len); - if (curr_length > best_length) { - best_length = curr_length; - best_distance = 1; - } - --iter; - // Skip the for loop if we already have the maximum. - if (best_length == MAX_LENGTH) pos = min_pos - 1; - } - best_argb = argb_start[best_length]; - - for (; pos >= min_pos && --iter; pos = chain[pos]) { - int curr_length; - assert(base_position > (uint32_t)pos); - - if (argb[pos + best_length] != best_argb) continue; - - curr_length = VP8LVectorMismatch(argb + pos, argb_start, max_len); - if (best_length < curr_length) { - best_length = curr_length; - best_distance = base_position - pos; - best_argb = argb_start[best_length]; - // Stop if we have reached a good enough length. - if (best_length >= length_max) break; - } - } - // We have the best match but in case the two intervals continue matching - // to the left, we have the best matches for the left-extended pixels. - max_base_position = base_position; - while (1) { - assert(best_length <= MAX_LENGTH); - assert(best_distance <= WINDOW_SIZE); - p->offset_length_[base_position] = - (best_distance << MAX_LENGTH_BITS) | (uint32_t)best_length; - --base_position; - // Stop if we don't have a match or if we are out of bounds. - if (best_distance == 0 || base_position == 0) break; - // Stop if we cannot extend the matching intervals to the left. - if (base_position < best_distance || - argb[base_position - best_distance] != argb[base_position]) { - break; - } - // Stop if we are matching at its limit because there could be a closer - // matching interval with the same maximum length. Then again, if the - // matching interval is as close as possible (best_distance == 1), we will - // never find anything better so let's continue. - if (best_length == MAX_LENGTH && best_distance != 1 && - base_position + MAX_LENGTH < max_base_position) { - break; - } - if (best_length < MAX_LENGTH) { - ++best_length; - max_base_position = base_position; - } - } - } - return 1; -} - -static WEBP_INLINE int HashChainFindOffset(const VP8LHashChain* const p, - const int base_position) { - return p->offset_length_[base_position] >> MAX_LENGTH_BITS; -} - -static WEBP_INLINE int HashChainFindLength(const VP8LHashChain* const p, - const int base_position) { - return p->offset_length_[base_position] & ((1U << MAX_LENGTH_BITS) - 1); -} - -static WEBP_INLINE void HashChainFindCopy(const VP8LHashChain* const p, - int base_position, - int* const offset_ptr, - int* const length_ptr) { - *offset_ptr = HashChainFindOffset(p, base_position); - *length_ptr = HashChainFindLength(p, base_position); -} - -static WEBP_INLINE void AddSingleLiteral(uint32_t pixel, int use_color_cache, - VP8LColorCache* const hashers, - VP8LBackwardRefs* const refs) { - PixOrCopy v; - if (use_color_cache) { - const uint32_t key = VP8LColorCacheGetIndex(hashers, pixel); - if (VP8LColorCacheLookup(hashers, key) == pixel) { - v = PixOrCopyCreateCacheIdx(key); - } else { - v = PixOrCopyCreateLiteral(pixel); - VP8LColorCacheSet(hashers, key, pixel); - } - } else { - v = PixOrCopyCreateLiteral(pixel); - } - BackwardRefsCursorAdd(refs, v); -} - -static int BackwardReferencesRle(int xsize, int ysize, - const uint32_t* const argb, - int cache_bits, VP8LBackwardRefs* const refs) { - const int pix_count = xsize * ysize; - int i, k; - const int use_color_cache = (cache_bits > 0); - VP8LColorCache hashers; - - if (use_color_cache && !VP8LColorCacheInit(&hashers, cache_bits)) { - return 0; - } - ClearBackwardRefs(refs); - // Add first pixel as literal. - AddSingleLiteral(argb[0], use_color_cache, &hashers, refs); - i = 1; - while (i < pix_count) { - const int max_len = MaxFindCopyLength(pix_count - i); - const int rle_len = FindMatchLength(argb + i, argb + i - 1, 0, max_len); - const int prev_row_len = (i < xsize) ? 0 : - FindMatchLength(argb + i, argb + i - xsize, 0, max_len); - if (rle_len >= prev_row_len && rle_len >= MIN_LENGTH) { - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, rle_len)); - // We don't need to update the color cache here since it is always the - // same pixel being copied, and that does not change the color cache - // state. - i += rle_len; - } else if (prev_row_len >= MIN_LENGTH) { - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(xsize, prev_row_len)); - if (use_color_cache) { - for (k = 0; k < prev_row_len; ++k) { - VP8LColorCacheInsert(&hashers, argb[i + k]); - } - } - i += prev_row_len; - } else { - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - i++; - } - } - if (use_color_cache) VP8LColorCacheClear(&hashers); - return !refs->error_; -} - -static int BackwardReferencesLz77(int xsize, int ysize, - const uint32_t* const argb, int cache_bits, - const VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs) { - int i; - int i_last_check = -1; - int ok = 0; - int cc_init = 0; - const int use_color_cache = (cache_bits > 0); - const int pix_count = xsize * ysize; - VP8LColorCache hashers; - - if (use_color_cache) { - cc_init = VP8LColorCacheInit(&hashers, cache_bits); - if (!cc_init) goto Error; - } - ClearBackwardRefs(refs); - for (i = 0; i < pix_count;) { - // Alternative#1: Code the pixels starting at 'i' using backward reference. - int offset = 0; - int len = 0; - int j; - HashChainFindCopy(hash_chain, i, &offset, &len); - if (len >= MIN_LENGTH) { - const int len_ini = len; - int max_reach = 0; - assert(i + len < pix_count); - // Only start from what we have not checked already. - i_last_check = (i > i_last_check) ? i : i_last_check; - // We know the best match for the current pixel but we try to find the - // best matches for the current pixel AND the next one combined. - // The naive method would use the intervals: - // [i,i+len) + [i+len, length of best match at i+len) - // while we check if we can use: - // [i,j) (where j<=i+len) + [j, length of best match at j) - for (j = i_last_check + 1; j <= i + len_ini; ++j) { - const int len_j = HashChainFindLength(hash_chain, j); - const int reach = - j + (len_j >= MIN_LENGTH ? len_j : 1); // 1 for single literal. - if (reach > max_reach) { - len = j - i; - max_reach = reach; - } - } - } else { - len = 1; - } - // Go with literal or backward reference. - assert(len > 0); - if (len == 1) { - AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); - } else { - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); - if (use_color_cache) { - for (j = i; j < i + len; ++j) VP8LColorCacheInsert(&hashers, argb[j]); - } - } - i += len; - } - - ok = !refs->error_; - Error: - if (cc_init) VP8LColorCacheClear(&hashers); - return ok; -} - -// ----------------------------------------------------------------------------- - -typedef struct { - double alpha_[VALUES_IN_BYTE]; - double red_[VALUES_IN_BYTE]; - double blue_[VALUES_IN_BYTE]; - double distance_[NUM_DISTANCE_CODES]; - double* literal_; -} CostModel; - -static int BackwardReferencesTraceBackwards( - int xsize, int ysize, const uint32_t* const argb, int quality, - int cache_bits, const VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs); - -static void ConvertPopulationCountTableToBitEstimates( - int num_symbols, const uint32_t population_counts[], double output[]) { - uint32_t sum = 0; - int nonzeros = 0; - int i; - for (i = 0; i < num_symbols; ++i) { - sum += population_counts[i]; - if (population_counts[i] > 0) { - ++nonzeros; - } - } - if (nonzeros <= 1) { - memset(output, 0, num_symbols * sizeof(*output)); - } else { - const double logsum = VP8LFastLog2(sum); - for (i = 0; i < num_symbols; ++i) { - output[i] = logsum - VP8LFastLog2(population_counts[i]); - } - } -} - -static int CostModelBuild(CostModel* const m, int cache_bits, - VP8LBackwardRefs* const refs) { - int ok = 0; - VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits); - if (histo == NULL) goto Error; - - VP8LHistogramCreate(histo, refs, cache_bits); - - ConvertPopulationCountTableToBitEstimates( - VP8LHistogramNumCodes(histo->palette_code_bits_), - histo->literal_, m->literal_); - ConvertPopulationCountTableToBitEstimates( - VALUES_IN_BYTE, histo->red_, m->red_); - ConvertPopulationCountTableToBitEstimates( - VALUES_IN_BYTE, histo->blue_, m->blue_); - ConvertPopulationCountTableToBitEstimates( - VALUES_IN_BYTE, histo->alpha_, m->alpha_); - ConvertPopulationCountTableToBitEstimates( - NUM_DISTANCE_CODES, histo->distance_, m->distance_); - ok = 1; - - Error: - VP8LFreeHistogram(histo); - return ok; -} - -static WEBP_INLINE double GetLiteralCost(const CostModel* const m, uint32_t v) { - return m->alpha_[v >> 24] + - m->red_[(v >> 16) & 0xff] + - m->literal_[(v >> 8) & 0xff] + - m->blue_[v & 0xff]; -} - -static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) { - const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx; - return m->literal_[literal_idx]; -} - -static WEBP_INLINE double GetLengthCost(const CostModel* const m, - uint32_t length) { - int code, extra_bits; - VP8LPrefixEncodeBits(length, &code, &extra_bits); - return m->literal_[VALUES_IN_BYTE + code] + extra_bits; -} - -static WEBP_INLINE double GetDistanceCost(const CostModel* const m, - uint32_t distance) { - int code, extra_bits; - VP8LPrefixEncodeBits(distance, &code, &extra_bits); - return m->distance_[code] + extra_bits; -} - -static void AddSingleLiteralWithCostModel(const uint32_t* const argb, - VP8LColorCache* const hashers, - const CostModel* const cost_model, - int idx, int use_color_cache, - double prev_cost, float* const cost, - uint16_t* const dist_array) { - double cost_val = prev_cost; - const uint32_t color = argb[0]; - const int ix = use_color_cache ? VP8LColorCacheContains(hashers, color) : -1; - if (ix >= 0) { - // use_color_cache is true and hashers contains color - const double mul0 = 0.68; - cost_val += GetCacheCost(cost_model, ix) * mul0; - } else { - const double mul1 = 0.82; - if (use_color_cache) VP8LColorCacheInsert(hashers, color); - cost_val += GetLiteralCost(cost_model, color) * mul1; - } - if (cost[idx] > cost_val) { - cost[idx] = (float)cost_val; - dist_array[idx] = 1; // only one is inserted. - } -} - -// ----------------------------------------------------------------------------- -// CostManager and interval handling - -// Empirical value to avoid high memory consumption but good for performance. -#define COST_CACHE_INTERVAL_SIZE_MAX 100 - -// To perform backward reference every pixel at index index_ is considered and -// the cost for the MAX_LENGTH following pixels computed. Those following pixels -// at index index_ + k (k from 0 to MAX_LENGTH) have a cost of: -// distance_cost_ at index_ + GetLengthCost(cost_model, k) -// (named cost) (named cached cost) -// and the minimum value is kept. GetLengthCost(cost_model, k) is cached in an -// array of size MAX_LENGTH. -// Instead of performing MAX_LENGTH comparisons per pixel, we keep track of the -// minimal values using intervals, for which lower_ and upper_ bounds are kept. -// An interval is defined by the index_ of the pixel that generated it and -// is only useful in a range of indices from start_ to end_ (exclusive), i.e. -// it contains the minimum value for pixels between start_ and end_. -// Intervals are stored in a linked list and ordered by start_. When a new -// interval has a better minimum, old intervals are split or removed. -typedef struct CostInterval CostInterval; -struct CostInterval { - double lower_; - double upper_; - int start_; - int end_; - double distance_cost_; - int index_; - CostInterval* previous_; - CostInterval* next_; -}; - -// The GetLengthCost(cost_model, k) part of the costs is also bounded for -// efficiency in a set of intervals of a different type. -// If those intervals are small enough, they are not used for comparison and -// written into the costs right away. -typedef struct { - double lower_; // Lower bound of the interval. - double upper_; // Upper bound of the interval. - int start_; - int end_; // Exclusive. - int do_write_; // If !=0, the interval is saved to cost instead of being kept - // for comparison. -} CostCacheInterval; - -// This structure is in charge of managing intervals and costs. -// It caches the different CostCacheInterval, caches the different -// GetLengthCost(cost_model, k) in cost_cache_ and the CostInterval's (whose -// count_ is limited by COST_CACHE_INTERVAL_SIZE_MAX). -#define COST_MANAGER_MAX_FREE_LIST 10 -typedef struct { - CostInterval* head_; - int count_; // The number of stored intervals. - CostCacheInterval* cache_intervals_; - size_t cache_intervals_size_; - double cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k). - double min_cost_cache_; // The minimum value in cost_cache_[1:]. - double max_cost_cache_; // The maximum value in cost_cache_[1:]. - float* costs_; - uint16_t* dist_array_; - // Most of the time, we only need few intervals -> use a free-list, to avoid - // fragmentation with small allocs in most common cases. - CostInterval intervals_[COST_MANAGER_MAX_FREE_LIST]; - CostInterval* free_intervals_; - // These are regularly malloc'd remains. This list can't grow larger than than - // size COST_CACHE_INTERVAL_SIZE_MAX - COST_MANAGER_MAX_FREE_LIST, note. - CostInterval* recycled_intervals_; - // Buffer used in BackwardReferencesHashChainDistanceOnly to store the ends - // of the intervals that can have impacted the cost at a pixel. - int* interval_ends_; - int interval_ends_size_; -} CostManager; - -static int IsCostCacheIntervalWritable(int start, int end) { - // 100 is the length for which we consider an interval for comparison, and not - // for writing. - // The first intervals are very small and go in increasing size. This constant - // helps merging them into one big interval (up to index 150/200 usually from - // which intervals start getting much bigger). - // This value is empirical. - return (end - start + 1 < 100); -} - -static void CostIntervalAddToFreeList(CostManager* const manager, - CostInterval* const interval) { - interval->next_ = manager->free_intervals_; - manager->free_intervals_ = interval; -} - -static int CostIntervalIsInFreeList(const CostManager* const manager, - const CostInterval* const interval) { - return (interval >= &manager->intervals_[0] && - interval <= &manager->intervals_[COST_MANAGER_MAX_FREE_LIST - 1]); -} - -static void CostManagerInitFreeList(CostManager* const manager) { - int i; - manager->free_intervals_ = NULL; - for (i = 0; i < COST_MANAGER_MAX_FREE_LIST; ++i) { - CostIntervalAddToFreeList(manager, &manager->intervals_[i]); - } -} - -static void DeleteIntervalList(CostManager* const manager, - const CostInterval* interval) { - while (interval != NULL) { - const CostInterval* const next = interval->next_; - if (!CostIntervalIsInFreeList(manager, interval)) { - WebPSafeFree((void*)interval); - } // else: do nothing - interval = next; - } -} - -static void CostManagerClear(CostManager* const manager) { - if (manager == NULL) return; - - WebPSafeFree(manager->costs_); - WebPSafeFree(manager->cache_intervals_); - WebPSafeFree(manager->interval_ends_); - - // Clear the interval lists. - DeleteIntervalList(manager, manager->head_); - manager->head_ = NULL; - DeleteIntervalList(manager, manager->recycled_intervals_); - manager->recycled_intervals_ = NULL; - - // Reset pointers, count_ and cache_intervals_size_. - memset(manager, 0, sizeof(*manager)); - CostManagerInitFreeList(manager); -} - -static int CostManagerInit(CostManager* const manager, - uint16_t* const dist_array, int pix_count, - const CostModel* const cost_model) { - int i; - const int cost_cache_size = (pix_count > MAX_LENGTH) ? MAX_LENGTH : pix_count; - // This constant is tied to the cost_model we use. - // Empirically, differences between intervals is usually of more than 1. - const double min_cost_diff = 0.1; - - manager->costs_ = NULL; - manager->cache_intervals_ = NULL; - manager->interval_ends_ = NULL; - manager->head_ = NULL; - manager->recycled_intervals_ = NULL; - manager->count_ = 0; - manager->dist_array_ = dist_array; - CostManagerInitFreeList(manager); - - // Fill in the cost_cache_. - manager->cache_intervals_size_ = 1; - manager->cost_cache_[0] = 0; - for (i = 1; i < cost_cache_size; ++i) { - manager->cost_cache_[i] = GetLengthCost(cost_model, i); - // Get an approximation of the number of bound intervals. - if (fabs(manager->cost_cache_[i] - manager->cost_cache_[i - 1]) > - min_cost_diff) { - ++manager->cache_intervals_size_; - } - // Compute the minimum of cost_cache_. - if (i == 1) { - manager->min_cost_cache_ = manager->cost_cache_[1]; - manager->max_cost_cache_ = manager->cost_cache_[1]; - } else if (manager->cost_cache_[i] < manager->min_cost_cache_) { - manager->min_cost_cache_ = manager->cost_cache_[i]; - } else if (manager->cost_cache_[i] > manager->max_cost_cache_) { - manager->max_cost_cache_ = manager->cost_cache_[i]; - } - } - - // With the current cost models, we have 15 intervals, so we are safe by - // setting a maximum of COST_CACHE_INTERVAL_SIZE_MAX. - if (manager->cache_intervals_size_ > COST_CACHE_INTERVAL_SIZE_MAX) { - manager->cache_intervals_size_ = COST_CACHE_INTERVAL_SIZE_MAX; - } - manager->cache_intervals_ = (CostCacheInterval*)WebPSafeMalloc( - manager->cache_intervals_size_, sizeof(*manager->cache_intervals_)); - if (manager->cache_intervals_ == NULL) { - CostManagerClear(manager); - return 0; - } - - // Fill in the cache_intervals_. - { - double cost_prev = -1e38f; // unprobably low initial value - CostCacheInterval* prev = NULL; - CostCacheInterval* cur = manager->cache_intervals_; - const CostCacheInterval* const end = - manager->cache_intervals_ + manager->cache_intervals_size_; - - // Consecutive values in cost_cache_ are compared and if a big enough - // difference is found, a new interval is created and bounded. - for (i = 0; i < cost_cache_size; ++i) { - const double cost_val = manager->cost_cache_[i]; - if (i == 0 || - (fabs(cost_val - cost_prev) > min_cost_diff && cur + 1 < end)) { - if (i > 1) { - const int is_writable = - IsCostCacheIntervalWritable(cur->start_, cur->end_); - // Merge with the previous interval if both are writable. - if (is_writable && cur != manager->cache_intervals_ && - prev->do_write_) { - // Update the previous interval. - prev->end_ = cur->end_; - if (cur->lower_ < prev->lower_) { - prev->lower_ = cur->lower_; - } else if (cur->upper_ > prev->upper_) { - prev->upper_ = cur->upper_; - } - } else { - cur->do_write_ = is_writable; - prev = cur; - ++cur; - } - } - // Initialize an interval. - cur->start_ = i; - cur->do_write_ = 0; - cur->lower_ = cost_val; - cur->upper_ = cost_val; - } else { - // Update the current interval bounds. - if (cost_val < cur->lower_) { - cur->lower_ = cost_val; - } else if (cost_val > cur->upper_) { - cur->upper_ = cost_val; - } - } - cur->end_ = i + 1; - cost_prev = cost_val; - } - manager->cache_intervals_size_ = cur + 1 - manager->cache_intervals_; - } - - manager->costs_ = (float*)WebPSafeMalloc(pix_count, sizeof(*manager->costs_)); - if (manager->costs_ == NULL) { - CostManagerClear(manager); - return 0; - } - // Set the initial costs_ high for every pixel as we will keep the minimum. - for (i = 0; i < pix_count; ++i) manager->costs_[i] = 1e38f; - - // The cost at pixel is influenced by the cost intervals from previous pixels. - // Let us take the specific case where the offset is the same (which actually - // happens a lot in case of uniform regions). - // pixel i contributes to j>i a cost of: offset cost + cost_cache_[j-i] - // pixel i+1 contributes to j>i a cost of: 2*offset cost + cost_cache_[j-i-1] - // pixel i+2 contributes to j>i a cost of: 3*offset cost + cost_cache_[j-i-2] - // and so on. - // A pixel i influences the following length(j) < MAX_LENGTH pixels. What is - // the value of j such that pixel i + j cannot influence any of those pixels? - // This value is such that: - // max of cost_cache_ < j*offset cost + min of cost_cache_ - // (pixel i + j 's cost cannot beat the worst cost given by pixel i). - // This value will be used to optimize the cost computation in - // BackwardReferencesHashChainDistanceOnly. - { - // The offset cost is computed in GetDistanceCost and has a minimum value of - // the minimum in cost_model->distance_. The case where the offset cost is 0 - // will be dealt with differently later so we are only interested in the - // minimum non-zero offset cost. - double offset_cost_min = 0.; - int size; - for (i = 0; i < NUM_DISTANCE_CODES; ++i) { - if (cost_model->distance_[i] != 0) { - if (offset_cost_min == 0.) { - offset_cost_min = cost_model->distance_[i]; - } else if (cost_model->distance_[i] < offset_cost_min) { - offset_cost_min = cost_model->distance_[i]; - } - } - } - // In case all the cost_model->distance_ is 0, the next non-zero cost we - // can have is from the extra bit in GetDistanceCost, hence 1. - if (offset_cost_min < 1.) offset_cost_min = 1.; - - size = 1 + (int)ceil((manager->max_cost_cache_ - manager->min_cost_cache_) / - offset_cost_min); - // Empirically, we usually end up with a value below 100. - if (size > MAX_LENGTH) size = MAX_LENGTH; - - manager->interval_ends_ = - (int*)WebPSafeMalloc(size, sizeof(*manager->interval_ends_)); - if (manager->interval_ends_ == NULL) { - CostManagerClear(manager); - return 0; - } - manager->interval_ends_size_ = size; - } - - return 1; -} - -// Given the distance_cost for pixel 'index', update the cost at pixel 'i' if it -// is smaller than the previously computed value. -static WEBP_INLINE void UpdateCost(CostManager* const manager, int i, int index, - double distance_cost) { - int k = i - index; - double cost_tmp; - assert(k >= 0 && k < MAX_LENGTH); - cost_tmp = distance_cost + manager->cost_cache_[k]; - - if (manager->costs_[i] > cost_tmp) { - manager->costs_[i] = (float)cost_tmp; - manager->dist_array_[i] = k + 1; - } -} - -// Given the distance_cost for pixel 'index', update the cost for all the pixels -// between 'start' and 'end' excluded. -static WEBP_INLINE void UpdateCostPerInterval(CostManager* const manager, - int start, int end, int index, - double distance_cost) { - int i; - for (i = start; i < end; ++i) UpdateCost(manager, i, index, distance_cost); -} - -// Given two intervals, make 'prev' be the previous one of 'next' in 'manager'. -static WEBP_INLINE void ConnectIntervals(CostManager* const manager, - CostInterval* const prev, - CostInterval* const next) { - if (prev != NULL) { - prev->next_ = next; - } else { - manager->head_ = next; - } - - if (next != NULL) next->previous_ = prev; -} - -// Pop an interval in the manager. -static WEBP_INLINE void PopInterval(CostManager* const manager, - CostInterval* const interval) { - CostInterval* const next = interval->next_; - - if (interval == NULL) return; - - ConnectIntervals(manager, interval->previous_, next); - if (CostIntervalIsInFreeList(manager, interval)) { - CostIntervalAddToFreeList(manager, interval); - } else { // recycle regularly malloc'd intervals too - interval->next_ = manager->recycled_intervals_; - manager->recycled_intervals_ = interval; - } - --manager->count_; - assert(manager->count_ >= 0); -} - -// Update the cost at index i by going over all the stored intervals that -// overlap with i. -static WEBP_INLINE void UpdateCostPerIndex(CostManager* const manager, int i) { - CostInterval* current = manager->head_; - - while (current != NULL && current->start_ <= i) { - if (current->end_ <= i) { - // We have an outdated interval, remove it. - CostInterval* next = current->next_; - PopInterval(manager, current); - current = next; - } else { - UpdateCost(manager, i, current->index_, current->distance_cost_); - current = current->next_; - } - } -} - -// Given a current orphan interval and its previous interval, before -// it was orphaned (which can be NULL), set it at the right place in the list -// of intervals using the start_ ordering and the previous interval as a hint. -static WEBP_INLINE void PositionOrphanInterval(CostManager* const manager, - CostInterval* const current, - CostInterval* previous) { - assert(current != NULL); - - if (previous == NULL) previous = manager->head_; - while (previous != NULL && current->start_ < previous->start_) { - previous = previous->previous_; - } - while (previous != NULL && previous->next_ != NULL && - previous->next_->start_ < current->start_) { - previous = previous->next_; - } - - if (previous != NULL) { - ConnectIntervals(manager, current, previous->next_); - } else { - ConnectIntervals(manager, current, manager->head_); - } - ConnectIntervals(manager, previous, current); -} - -// Insert an interval in the list contained in the manager by starting at -// interval_in as a hint. The intervals are sorted by start_ value. -static WEBP_INLINE void InsertInterval(CostManager* const manager, - CostInterval* const interval_in, - double distance_cost, double lower, - double upper, int index, int start, - int end) { - CostInterval* interval_new; - - if (IsCostCacheIntervalWritable(start, end) || - manager->count_ >= COST_CACHE_INTERVAL_SIZE_MAX) { - // Write down the interval if it is too small. - UpdateCostPerInterval(manager, start, end, index, distance_cost); - return; - } - if (manager->free_intervals_ != NULL) { - interval_new = manager->free_intervals_; - manager->free_intervals_ = interval_new->next_; - } else if (manager->recycled_intervals_ != NULL) { - interval_new = manager->recycled_intervals_; - manager->recycled_intervals_ = interval_new->next_; - } else { // malloc for good - interval_new = (CostInterval*)WebPSafeMalloc(1, sizeof(*interval_new)); - if (interval_new == NULL) { - // Write down the interval if we cannot create it. - UpdateCostPerInterval(manager, start, end, index, distance_cost); - return; - } - } - - interval_new->distance_cost_ = distance_cost; - interval_new->lower_ = lower; - interval_new->upper_ = upper; - interval_new->index_ = index; - interval_new->start_ = start; - interval_new->end_ = end; - PositionOrphanInterval(manager, interval_new, interval_in); - - ++manager->count_; -} - -// When an interval has its start_ or end_ modified, it needs to be -// repositioned in the linked list. -static WEBP_INLINE void RepositionInterval(CostManager* const manager, - CostInterval* const interval) { - if (IsCostCacheIntervalWritable(interval->start_, interval->end_)) { - // Maybe interval has been resized and is small enough to be removed. - UpdateCostPerInterval(manager, interval->start_, interval->end_, - interval->index_, interval->distance_cost_); - PopInterval(manager, interval); - return; - } - - // Early exit if interval is at the right spot. - if ((interval->previous_ == NULL || - interval->previous_->start_ <= interval->start_) && - (interval->next_ == NULL || - interval->start_ <= interval->next_->start_)) { - return; - } - - ConnectIntervals(manager, interval->previous_, interval->next_); - PositionOrphanInterval(manager, interval, interval->previous_); -} - -// Given a new cost interval defined by its start at index, its last value and -// distance_cost, add its contributions to the previous intervals and costs. -// If handling the interval or one of its subintervals becomes to heavy, its -// contribution is added to the costs right away. -static WEBP_INLINE void PushInterval(CostManager* const manager, - double distance_cost, int index, - int last) { - size_t i; - CostInterval* interval = manager->head_; - CostInterval* interval_next; - const CostCacheInterval* const cost_cache_intervals = - manager->cache_intervals_; - - for (i = 0; i < manager->cache_intervals_size_ && - cost_cache_intervals[i].start_ < last; - ++i) { - // Define the intersection of the ith interval with the new one. - int start = index + cost_cache_intervals[i].start_; - const int end = index + (cost_cache_intervals[i].end_ > last - ? last - : cost_cache_intervals[i].end_); - const double lower_in = cost_cache_intervals[i].lower_; - const double upper_in = cost_cache_intervals[i].upper_; - const double lower_full_in = distance_cost + lower_in; - const double upper_full_in = distance_cost + upper_in; - - if (cost_cache_intervals[i].do_write_) { - UpdateCostPerInterval(manager, start, end, index, distance_cost); - continue; - } - - for (; interval != NULL && interval->start_ < end && start < end; - interval = interval_next) { - const double lower_full_interval = - interval->distance_cost_ + interval->lower_; - const double upper_full_interval = - interval->distance_cost_ + interval->upper_; - - interval_next = interval->next_; - - // Make sure we have some overlap - if (start >= interval->end_) continue; - - if (lower_full_in >= upper_full_interval) { - // When intervals are represented, the lower, the better. - // [**********************************************************] - // start end - // [----------------------------------] - // interval->start_ interval->end_ - // If we are worse than what we already have, add whatever we have so - // far up to interval. - const int start_new = interval->end_; - InsertInterval(manager, interval, distance_cost, lower_in, upper_in, - index, start, interval->start_); - start = start_new; - continue; - } - - // We know the two intervals intersect. - if (upper_full_in >= lower_full_interval) { - // There is no clear cut on which is best, so let's keep both. - // [*********[*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*]***********] - // start interval->start_ interval->end_ end - // OR - // [*********[*-*-*-*-*-*-*-*-*-*-*-]----------------------] - // start interval->start_ end interval->end_ - const int end_new = (interval->end_ <= end) ? interval->end_ : end; - InsertInterval(manager, interval, distance_cost, lower_in, upper_in, - index, start, end_new); - start = end_new; - } else if (start <= interval->start_ && interval->end_ <= end) { - // [----------------------------------] - // interval->start_ interval->end_ - // [**************************************************************] - // start end - // We can safely remove the old interval as it is fully included. - PopInterval(manager, interval); - } else { - if (interval->start_ <= start && end <= interval->end_) { - // [--------------------------------------------------------------] - // interval->start_ interval->end_ - // [*****************************] - // start end - // We have to split the old interval as it fully contains the new one. - const int end_original = interval->end_; - interval->end_ = start; - InsertInterval(manager, interval, interval->distance_cost_, - interval->lower_, interval->upper_, interval->index_, - end, end_original); - } else if (interval->start_ < start) { - // [------------------------------------] - // interval->start_ interval->end_ - // [*****************************] - // start end - interval->end_ = start; - } else { - // [------------------------------------] - // interval->start_ interval->end_ - // [*****************************] - // start end - interval->start_ = end; - } - - // The interval has been modified, we need to reposition it or write it. - RepositionInterval(manager, interval); - } - } - // Insert the remaining interval from start to end. - InsertInterval(manager, interval, distance_cost, lower_in, upper_in, index, - start, end); - } -} - -static int BackwardReferencesHashChainDistanceOnly( - int xsize, int ysize, const uint32_t* const argb, int quality, - int cache_bits, const VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs, uint16_t* const dist_array) { - int i; - int ok = 0; - int cc_init = 0; - const int pix_count = xsize * ysize; - const int use_color_cache = (cache_bits > 0); - const size_t literal_array_size = sizeof(double) * - (NUM_LITERAL_CODES + NUM_LENGTH_CODES + - ((cache_bits > 0) ? (1 << cache_bits) : 0)); - const size_t cost_model_size = sizeof(CostModel) + literal_array_size; - CostModel* const cost_model = - (CostModel*)WebPSafeCalloc(1ULL, cost_model_size); - VP8LColorCache hashers; - const int skip_length = 32 + quality; - const int skip_min_distance_code = 2; - CostManager* cost_manager = - (CostManager*)WebPSafeMalloc(1ULL, sizeof(*cost_manager)); - - if (cost_model == NULL || cost_manager == NULL) goto Error; - - cost_model->literal_ = (double*)(cost_model + 1); - if (use_color_cache) { - cc_init = VP8LColorCacheInit(&hashers, cache_bits); - if (!cc_init) goto Error; - } - - if (!CostModelBuild(cost_model, cache_bits, refs)) { - goto Error; - } - - if (!CostManagerInit(cost_manager, dist_array, pix_count, cost_model)) { - goto Error; - } - - // We loop one pixel at a time, but store all currently best points to - // non-processed locations from this point. - dist_array[0] = 0; - // Add first pixel as literal. - AddSingleLiteralWithCostModel(argb + 0, &hashers, cost_model, 0, - use_color_cache, 0.0, cost_manager->costs_, - dist_array); - - for (i = 1; i < pix_count - 1; ++i) { - int offset = 0, len = 0; - double prev_cost = cost_manager->costs_[i - 1]; - HashChainFindCopy(hash_chain, i, &offset, &len); - if (len >= 2) { - // If we are dealing with a non-literal. - const int code = DistanceToPlaneCode(xsize, offset); - const double offset_cost = GetDistanceCost(cost_model, code); - const int first_i = i; - int j_max = 0, interval_ends_index = 0; - const int is_offset_zero = (offset_cost == 0.); - - if (!is_offset_zero) { - j_max = (int)ceil( - (cost_manager->max_cost_cache_ - cost_manager->min_cost_cache_) / - offset_cost); - if (j_max < 1) { - j_max = 1; - } else if (j_max > cost_manager->interval_ends_size_ - 1) { - // This could only happen in the case of MAX_LENGTH. - j_max = cost_manager->interval_ends_size_ - 1; - } - } // else j_max is unused anyway. - - // Instead of considering all contributions from a pixel i by calling: - // PushInterval(cost_manager, prev_cost + offset_cost, i, len); - // we optimize these contributions in case offset_cost stays the same for - // consecutive pixels. This describes a set of pixels similar to a - // previous set (e.g. constant color regions). - for (; i < pix_count - 1; ++i) { - int offset_next, len_next; - prev_cost = cost_manager->costs_[i - 1]; - - if (is_offset_zero) { - // No optimization can be made so we just push all of the - // contributions from i. - PushInterval(cost_manager, prev_cost, i, len); - } else { - // j_max is chosen as the smallest j such that: - // max of cost_cache_ < j*offset cost + min of cost_cache_ - // Therefore, the pixel influenced by i-j_max, cannot be influenced - // by i. Only the costs after the end of what i contributed need to be - // updated. cost_manager->interval_ends_ is a circular buffer that - // stores those ends. - const double distance_cost = prev_cost + offset_cost; - int j = cost_manager->interval_ends_[interval_ends_index]; - if (i - first_i <= j_max || - !IsCostCacheIntervalWritable(j, i + len)) { - PushInterval(cost_manager, distance_cost, i, len); - } else { - for (; j < i + len; ++j) { - UpdateCost(cost_manager, j, i, distance_cost); - } - } - // Store the new end in the circular buffer. - assert(interval_ends_index < cost_manager->interval_ends_size_); - cost_manager->interval_ends_[interval_ends_index] = i + len; - if (++interval_ends_index > j_max) interval_ends_index = 0; - } - - // Check whether i is the last pixel to consider, as it is handled - // differently. - if (i + 1 >= pix_count - 1) break; - HashChainFindCopy(hash_chain, i + 1, &offset_next, &len_next); - if (offset_next != offset) break; - len = len_next; - UpdateCostPerIndex(cost_manager, i); - AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i, - use_color_cache, prev_cost, - cost_manager->costs_, dist_array); - } - // Submit the last pixel. - UpdateCostPerIndex(cost_manager, i + 1); - - // This if is for speedup only. It roughly doubles the speed, and - // makes compression worse by .1 %. - if (len >= skip_length && code <= skip_min_distance_code) { - // Long copy for short distances, let's skip the middle - // lookups for better copies. - // 1) insert the hashes. - if (use_color_cache) { - int k; - for (k = 0; k < len; ++k) { - VP8LColorCacheInsert(&hashers, argb[i + k]); - } - } - // 2) jump. - { - const int i_next = i + len - 1; // for loop does ++i, thus -1 here. - for (; i <= i_next; ++i) UpdateCostPerIndex(cost_manager, i + 1); - i = i_next; - } - goto next_symbol; - } - if (len > 2) { - // Also try the smallest interval possible (size 2). - double cost_total = - prev_cost + offset_cost + GetLengthCost(cost_model, 1); - if (cost_manager->costs_[i + 1] > cost_total) { - cost_manager->costs_[i + 1] = (float)cost_total; - dist_array[i + 1] = 2; - } - } - } else { - // The pixel is added as a single literal so just update the costs. - UpdateCostPerIndex(cost_manager, i + 1); - } - - AddSingleLiteralWithCostModel(argb + i, &hashers, cost_model, i, - use_color_cache, prev_cost, - cost_manager->costs_, dist_array); - - next_symbol: ; - } - // Handle the last pixel. - if (i == (pix_count - 1)) { - AddSingleLiteralWithCostModel( - argb + i, &hashers, cost_model, i, use_color_cache, - cost_manager->costs_[pix_count - 2], cost_manager->costs_, dist_array); - } - - ok = !refs->error_; - Error: - if (cc_init) VP8LColorCacheClear(&hashers); - CostManagerClear(cost_manager); - WebPSafeFree(cost_model); - WebPSafeFree(cost_manager); - return ok; -} - -// We pack the path at the end of *dist_array and return -// a pointer to this part of the array. Example: -// dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232] -static void TraceBackwards(uint16_t* const dist_array, - int dist_array_size, - uint16_t** const chosen_path, - int* const chosen_path_size) { - uint16_t* path = dist_array + dist_array_size; - uint16_t* cur = dist_array + dist_array_size - 1; - while (cur >= dist_array) { - const int k = *cur; - --path; - *path = k; - cur -= k; - } - *chosen_path = path; - *chosen_path_size = (int)(dist_array + dist_array_size - path); -} - -static int BackwardReferencesHashChainFollowChosenPath( - const uint32_t* const argb, int cache_bits, - const uint16_t* const chosen_path, int chosen_path_size, - const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs) { - const int use_color_cache = (cache_bits > 0); - int ix; - int i = 0; - int ok = 0; - int cc_init = 0; - VP8LColorCache hashers; - - if (use_color_cache) { - cc_init = VP8LColorCacheInit(&hashers, cache_bits); - if (!cc_init) goto Error; - } - - ClearBackwardRefs(refs); - for (ix = 0; ix < chosen_path_size; ++ix) { - const int len = chosen_path[ix]; - if (len != 1) { - int k; - const int offset = HashChainFindOffset(hash_chain, i); - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); - if (use_color_cache) { - for (k = 0; k < len; ++k) { - VP8LColorCacheInsert(&hashers, argb[i + k]); - } - } - i += len; - } else { - PixOrCopy v; - const int idx = - use_color_cache ? VP8LColorCacheContains(&hashers, argb[i]) : -1; - if (idx >= 0) { - // use_color_cache is true and hashers contains argb[i] - // push pixel as a color cache index - v = PixOrCopyCreateCacheIdx(idx); - } else { - if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); - v = PixOrCopyCreateLiteral(argb[i]); - } - BackwardRefsCursorAdd(refs, v); - ++i; - } - } - ok = !refs->error_; - Error: - if (cc_init) VP8LColorCacheClear(&hashers); - return ok; -} - -// Returns 1 on success. -static int BackwardReferencesTraceBackwards( - int xsize, int ysize, const uint32_t* const argb, int quality, - int cache_bits, const VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs) { - int ok = 0; - const int dist_array_size = xsize * ysize; - uint16_t* chosen_path = NULL; - int chosen_path_size = 0; - uint16_t* dist_array = - (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array)); - - if (dist_array == NULL) goto Error; - - if (!BackwardReferencesHashChainDistanceOnly( - xsize, ysize, argb, quality, cache_bits, hash_chain, - refs, dist_array)) { - goto Error; - } - TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size); - if (!BackwardReferencesHashChainFollowChosenPath( - argb, cache_bits, chosen_path, chosen_path_size, hash_chain, refs)) { - goto Error; - } - ok = 1; - Error: - WebPSafeFree(dist_array); - return ok; -} - -static void BackwardReferences2DLocality(int xsize, - const VP8LBackwardRefs* const refs) { - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - while (VP8LRefsCursorOk(&c)) { - if (PixOrCopyIsCopy(c.cur_pos)) { - const int dist = c.cur_pos->argb_or_distance; - const int transformed_dist = DistanceToPlaneCode(xsize, dist); - c.cur_pos->argb_or_distance = transformed_dist; - } - VP8LRefsCursorNext(&c); - } -} - -// Computes the entropies for a color cache size (in bits) between 0 (unused) -// and cache_bits_max (inclusive). -// Returns 1 on success, 0 in case of allocation error. -static int ComputeCacheEntropies(const uint32_t* argb, - const VP8LBackwardRefs* const refs, - int cache_bits_max, double entropies[]) { - int cc_init[MAX_COLOR_CACHE_BITS + 1] = { 0 }; - VP8LColorCache hashers[MAX_COLOR_CACHE_BITS + 1]; - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - VP8LHistogram* histos[MAX_COLOR_CACHE_BITS + 1] = { NULL }; - int ok = 0; - int i; - - for (i = 0; i <= cache_bits_max; ++i) { - histos[i] = VP8LAllocateHistogram(i); - if (histos[i] == NULL) goto Error; - if (i == 0) continue; - cc_init[i] = VP8LColorCacheInit(&hashers[i], i); - if (!cc_init[i]) goto Error; - } - - assert(cache_bits_max >= 0); - // Do not use the color cache for cache_bits=0. - while (VP8LRefsCursorOk(&c)) { - VP8LHistogramAddSinglePixOrCopy(histos[0], c.cur_pos); - VP8LRefsCursorNext(&c); - } - if (cache_bits_max > 0) { - c = VP8LRefsCursorInit(refs); - while (VP8LRefsCursorOk(&c)) { - const PixOrCopy* const v = c.cur_pos; - if (PixOrCopyIsLiteral(v)) { - const uint32_t pix = *argb++; - // The keys of the caches can be derived from the longest one. - int key = HashPix(pix, 32 - cache_bits_max); - for (i = cache_bits_max; i >= 1; --i, key >>= 1) { - if (VP8LColorCacheLookup(&hashers[i], key) == pix) { - ++histos[i]->literal_[NUM_LITERAL_CODES + NUM_LENGTH_CODES + key]; - } else { - VP8LColorCacheSet(&hashers[i], key, pix); - ++histos[i]->blue_[pix & 0xff]; - ++histos[i]->literal_[(pix >> 8) & 0xff]; - ++histos[i]->red_[(pix >> 16) & 0xff]; - ++histos[i]->alpha_[pix >> 24]; - } - } - } else { - // Update the histograms for distance/length. - int len = PixOrCopyLength(v); - int code_dist, code_len, extra_bits; - uint32_t argb_prev = *argb ^ 0xffffffffu; - VP8LPrefixEncodeBits(len, &code_len, &extra_bits); - VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code_dist, &extra_bits); - for (i = 1; i <= cache_bits_max; ++i) { - ++histos[i]->literal_[NUM_LITERAL_CODES + code_len]; - ++histos[i]->distance_[code_dist]; - } - // Update the colors caches. - do { - if (*argb != argb_prev) { - // Efficiency: insert only if the color changes. - int key = HashPix(*argb, 32 - cache_bits_max); - for (i = cache_bits_max; i >= 1; --i, key >>= 1) { - hashers[i].colors_[key] = *argb; - } - argb_prev = *argb; - } - argb++; - } while (--len != 0); - } - VP8LRefsCursorNext(&c); - } - } - for (i = 0; i <= cache_bits_max; ++i) { - entropies[i] = VP8LHistogramEstimateBits(histos[i]); - } - ok = 1; -Error: - for (i = 0; i <= cache_bits_max; ++i) { - if (cc_init[i]) VP8LColorCacheClear(&hashers[i]); - VP8LFreeHistogram(histos[i]); - } - return ok; -} - -// Evaluate optimal cache bits for the local color cache. -// The input *best_cache_bits sets the maximum cache bits to use (passing 0 -// implies disabling the local color cache). The local color cache is also -// disabled for the lower (<= 25) quality. -// Returns 0 in case of memory error. -static int CalculateBestCacheSize(const uint32_t* const argb, - int xsize, int ysize, int quality, - const VP8LHashChain* const hash_chain, - VP8LBackwardRefs* const refs, - int* const lz77_computed, - int* const best_cache_bits) { - int i; - int cache_bits_high = (quality <= 25) ? 0 : *best_cache_bits; - double entropy_min = MAX_ENTROPY; - double entropies[MAX_COLOR_CACHE_BITS + 1]; - - assert(cache_bits_high <= MAX_COLOR_CACHE_BITS); - - *lz77_computed = 0; - if (cache_bits_high == 0) { - *best_cache_bits = 0; - // Local color cache is disabled. - return 1; - } - // Compute LZ77 with no cache (0 bits), as the ideal LZ77 with a color cache - // is not that different in practice. - if (!BackwardReferencesLz77(xsize, ysize, argb, 0, hash_chain, refs)) { - return 0; - } - // Find the cache_bits giving the lowest entropy. The search is done in a - // brute-force way as the function (entropy w.r.t cache_bits) can be - // anything in practice. - if (!ComputeCacheEntropies(argb, refs, cache_bits_high, entropies)) { - return 0; - } - for (i = 0; i <= cache_bits_high; ++i) { - if (i == 0 || entropies[i] < entropy_min) { - entropy_min = entropies[i]; - *best_cache_bits = i; - } - } - return 1; -} - -// Update (in-place) backward references for specified cache_bits. -static int BackwardRefsWithLocalCache(const uint32_t* const argb, - int cache_bits, - VP8LBackwardRefs* const refs) { - int pixel_index = 0; - VP8LColorCache hashers; - VP8LRefsCursor c = VP8LRefsCursorInit(refs); - if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0; - - while (VP8LRefsCursorOk(&c)) { - PixOrCopy* const v = c.cur_pos; - if (PixOrCopyIsLiteral(v)) { - const uint32_t argb_literal = v->argb_or_distance; - const int ix = VP8LColorCacheContains(&hashers, argb_literal); - if (ix >= 0) { - // hashers contains argb_literal - *v = PixOrCopyCreateCacheIdx(ix); - } else { - VP8LColorCacheInsert(&hashers, argb_literal); - } - ++pixel_index; - } else { - // refs was created without local cache, so it can not have cache indexes. - int k; - assert(PixOrCopyIsCopy(v)); - for (k = 0; k < v->len; ++k) { - VP8LColorCacheInsert(&hashers, argb[pixel_index++]); - } - } - VP8LRefsCursorNext(&c); - } - VP8LColorCacheClear(&hashers); - return 1; -} - -static VP8LBackwardRefs* GetBackwardReferencesLowEffort( - int width, int height, const uint32_t* const argb, - int* const cache_bits, const VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2]) { - VP8LBackwardRefs* refs_lz77 = &refs_array[0]; - *cache_bits = 0; - if (!BackwardReferencesLz77(width, height, argb, 0, hash_chain, refs_lz77)) { - return NULL; - } - BackwardReferences2DLocality(width, refs_lz77); - return refs_lz77; -} - -static VP8LBackwardRefs* GetBackwardReferences( - int width, int height, const uint32_t* const argb, int quality, - int* const cache_bits, const VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2]) { - int lz77_is_useful; - int lz77_computed; - double bit_cost_lz77, bit_cost_rle; - VP8LBackwardRefs* best = NULL; - VP8LBackwardRefs* refs_lz77 = &refs_array[0]; - VP8LBackwardRefs* refs_rle = &refs_array[1]; - VP8LHistogram* histo = NULL; - - if (!CalculateBestCacheSize(argb, width, height, quality, hash_chain, - refs_lz77, &lz77_computed, cache_bits)) { - goto Error; - } - - if (lz77_computed) { - // Transform refs_lz77 for the optimized cache_bits. - if (*cache_bits > 0) { - if (!BackwardRefsWithLocalCache(argb, *cache_bits, refs_lz77)) { - goto Error; - } - } - } else { - if (!BackwardReferencesLz77(width, height, argb, *cache_bits, hash_chain, - refs_lz77)) { - goto Error; - } - } - - if (!BackwardReferencesRle(width, height, argb, *cache_bits, refs_rle)) { - goto Error; - } - - histo = VP8LAllocateHistogram(*cache_bits); - if (histo == NULL) goto Error; - - { - // Evaluate LZ77 coding. - VP8LHistogramCreate(histo, refs_lz77, *cache_bits); - bit_cost_lz77 = VP8LHistogramEstimateBits(histo); - // Evaluate RLE coding. - VP8LHistogramCreate(histo, refs_rle, *cache_bits); - bit_cost_rle = VP8LHistogramEstimateBits(histo); - // Decide if LZ77 is useful. - lz77_is_useful = (bit_cost_lz77 < bit_cost_rle); - } - - // Choose appropriate backward reference. - if (lz77_is_useful) { - // TraceBackwards is costly. Don't execute it at lower quality. - const int try_lz77_trace_backwards = (quality >= 25); - best = refs_lz77; // default guess: lz77 is better - if (try_lz77_trace_backwards) { - VP8LBackwardRefs* const refs_trace = refs_rle; - if (!VP8LBackwardRefsCopy(refs_lz77, refs_trace)) { - best = NULL; - goto Error; - } - if (BackwardReferencesTraceBackwards(width, height, argb, quality, - *cache_bits, hash_chain, - refs_trace)) { - double bit_cost_trace; - // Evaluate LZ77 coding. - VP8LHistogramCreate(histo, refs_trace, *cache_bits); - bit_cost_trace = VP8LHistogramEstimateBits(histo); - if (bit_cost_trace < bit_cost_lz77) { - best = refs_trace; - } - } - } - } else { - best = refs_rle; - } - - BackwardReferences2DLocality(width, best); - - Error: - VP8LFreeHistogram(histo); - return best; -} - -VP8LBackwardRefs* VP8LGetBackwardReferences( - int width, int height, const uint32_t* const argb, int quality, - int low_effort, int* const cache_bits, - const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[2]) { - if (low_effort) { - return GetBackwardReferencesLowEffort(width, height, argb, cache_bits, - hash_chain, refs_array); - } else { - return GetBackwardReferences(width, height, argb, quality, cache_bits, - hash_chain, refs_array); - } -} diff --git a/3rdparty/libwebp/mux/Makefile.am b/3rdparty/libwebp/mux/Makefile.am deleted file mode 100644 index 47b1fbe12b..0000000000 --- a/3rdparty/libwebp/mux/Makefile.am +++ /dev/null @@ -1,19 +0,0 @@ -lib_LTLIBRARIES = libwebpmux.la - -libwebpmux_la_SOURCES = -libwebpmux_la_SOURCES += anim_encode.c -libwebpmux_la_SOURCES += animi.h -libwebpmux_la_SOURCES += muxedit.c -libwebpmux_la_SOURCES += muxi.h -libwebpmux_la_SOURCES += muxinternal.c -libwebpmux_la_SOURCES += muxread.c - -libwebpmuxinclude_HEADERS = -libwebpmuxinclude_HEADERS += ../webp/mux.h -libwebpmuxinclude_HEADERS += ../webp/mux_types.h -libwebpmuxinclude_HEADERS += ../webp/types.h - -libwebpmux_la_LIBADD = ../libwebp.la -libwebpmux_la_LDFLAGS = -no-undefined -version-info 3:0:0 -lm -libwebpmuxincludedir = $(includedir)/webp -pkgconfig_DATA = libwebpmux.pc diff --git a/3rdparty/libwebp/mux/libwebpmux.pc.in b/3rdparty/libwebp/mux/libwebpmux.pc.in deleted file mode 100644 index a96fac7850..0000000000 --- a/3rdparty/libwebp/mux/libwebpmux.pc.in +++ /dev/null @@ -1,12 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libwebpmux -Description: Library for manipulating the WebP graphics format container -Version: @PACKAGE_VERSION@ -Requires: libwebp >= 0.2.0 -Cflags: -I${includedir} -Libs: -L${libdir} -lwebpmux -Libs.private: -lm diff --git a/3rdparty/libwebp/mux/libwebpmux.rc b/3rdparty/libwebp/mux/libwebpmux.rc deleted file mode 100644 index 7f9a33a07a..0000000000 --- a/3rdparty/libwebp/mux/libwebpmux.rc +++ /dev/null @@ -1,41 +0,0 @@ -#define APSTUDIO_READONLY_SYMBOLS -#include "winres.h" -#undef APSTUDIO_READONLY_SYMBOLS - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,4,0,0 - PRODUCTVERSION 0,4,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", "Google, Inc." - VALUE "FileDescription", "libwebpmux DLL" - VALUE "FileVersion", "0.4.0" - VALUE "InternalName", "libwebpmux.dll" - VALUE "LegalCopyright", "Copyright (C) 2017" - VALUE "OriginalFilename", "libwebpmux.dll" - VALUE "ProductName", "WebP Image Muxer" - VALUE "ProductVersion", "0.4.0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // English (United States) resources diff --git a/3rdparty/libwebp/dec/alpha_dec.c b/3rdparty/libwebp/src/dec/alpha_dec.c similarity index 97% rename from 3rdparty/libwebp/dec/alpha_dec.c rename to 3rdparty/libwebp/src/dec/alpha_dec.c index 83ffd4b609..bce735bfc2 100644 --- a/3rdparty/libwebp/dec/alpha_dec.c +++ b/3rdparty/libwebp/src/dec/alpha_dec.c @@ -12,13 +12,13 @@ // Author: Skal (pascal.massimino@gmail.com) #include -#include "./alphai_dec.h" -#include "./vp8i_dec.h" -#include "./vp8li_dec.h" -#include "../dsp/dsp.h" -#include "../utils/quant_levels_dec_utils.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dsp/dsp.h" +#include "src/utils/quant_levels_dec_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" //------------------------------------------------------------------------------ // ALPHDecoder object. diff --git a/3rdparty/libwebp/dec/alphai_dec.h b/3rdparty/libwebp/src/dec/alphai_dec.h similarity index 89% rename from 3rdparty/libwebp/dec/alphai_dec.h rename to 3rdparty/libwebp/src/dec/alphai_dec.h index 561e8151ee..e0fa281a55 100644 --- a/3rdparty/libwebp/dec/alphai_dec.h +++ b/3rdparty/libwebp/src/dec/alphai_dec.h @@ -11,11 +11,11 @@ // // Author: Urvang (urvang@google.com) -#ifndef WEBP_DEC_ALPHAI_H_ -#define WEBP_DEC_ALPHAI_H_ +#ifndef WEBP_DEC_ALPHAI_DEC_H_ +#define WEBP_DEC_ALPHAI_DEC_H_ -#include "./webpi_dec.h" -#include "../utils/filters_utils.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/filters_utils.h" #ifdef __cplusplus extern "C" { @@ -51,4 +51,4 @@ void WebPDeallocateAlphaMemory(VP8Decoder* const dec); } // extern "C" #endif -#endif /* WEBP_DEC_ALPHAI_H_ */ +#endif /* WEBP_DEC_ALPHAI_DEC_H_ */ diff --git a/3rdparty/libwebp/dec/buffer_dec.c b/3rdparty/libwebp/src/dec/buffer_dec.c similarity index 90% rename from 3rdparty/libwebp/dec/buffer_dec.c rename to 3rdparty/libwebp/src/dec/buffer_dec.c index c685fd5646..75eb3c40b4 100644 --- a/3rdparty/libwebp/dec/buffer_dec.c +++ b/3rdparty/libwebp/src/dec/buffer_dec.c @@ -13,15 +13,15 @@ #include -#include "./vp8i_dec.h" -#include "./webpi_dec.h" -#include "../utils/utils.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // WebPDecBuffer // Number of bytes per pixel for the different color-spaces. -static const int kModeBpp[MODE_LAST] = { +static const uint8_t kModeBpp[MODE_LAST] = { 3, 4, 3, 4, 4, 2, 2, 4, 4, 4, 2, // pre-multiplied modes 1, 1 }; @@ -36,7 +36,7 @@ static int IsValidColorspace(int webp_csp_mode) { // strictly speaking, the very last (or first, if flipped) row // doesn't require padding. #define MIN_BUFFER_SIZE(WIDTH, HEIGHT, STRIDE) \ - (uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH) + ((uint64_t)(STRIDE) * ((HEIGHT) - 1) + (WIDTH)) static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { int ok = 1; @@ -98,9 +98,14 @@ static VP8StatusCode AllocateBuffer(WebPDecBuffer* const buffer) { uint64_t uv_size = 0, a_size = 0, total_size; // We need memory and it hasn't been allocated yet. // => initialize output buffer, now that dimensions are known. - const int stride = w * kModeBpp[mode]; - const uint64_t size = (uint64_t)stride * h; + int stride; + uint64_t size; + if ((uint64_t)w * kModeBpp[mode] >= (1ull << 32)) { + return VP8_STATUS_INVALID_PARAM; + } + stride = w * kModeBpp[mode]; + size = (uint64_t)stride * h; if (!WebPIsRGBMode(mode)) { uv_stride = (w + 1) / 2; uv_size = (uint64_t)uv_stride * ((h + 1) / 2); @@ -169,11 +174,11 @@ VP8StatusCode WebPFlipBuffer(WebPDecBuffer* const buffer) { return VP8_STATUS_OK; } -VP8StatusCode WebPAllocateDecBuffer(int w, int h, +VP8StatusCode WebPAllocateDecBuffer(int width, int height, const WebPDecoderOptions* const options, - WebPDecBuffer* const out) { + WebPDecBuffer* const buffer) { VP8StatusCode status; - if (out == NULL || w <= 0 || h <= 0) { + if (buffer == NULL || width <= 0 || height <= 0) { return VP8_STATUS_INVALID_PARAM; } if (options != NULL) { // First, apply options if there is any. @@ -182,33 +187,39 @@ VP8StatusCode WebPAllocateDecBuffer(int w, int h, const int ch = options->crop_height; const int x = options->crop_left & ~1; const int y = options->crop_top & ~1; - if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || x + cw > w || y + ch > h) { + if (x < 0 || y < 0 || cw <= 0 || ch <= 0 || + x + cw > width || y + ch > height) { return VP8_STATUS_INVALID_PARAM; // out of frame boundary. } - w = cw; - h = ch; + width = cw; + height = ch; } + if (options->use_scaling) { +#if !defined(WEBP_REDUCE_SIZE) int scaled_width = options->scaled_width; int scaled_height = options->scaled_height; if (!WebPRescalerGetScaledDimensions( - w, h, &scaled_width, &scaled_height)) { + width, height, &scaled_width, &scaled_height)) { return VP8_STATUS_INVALID_PARAM; } - w = scaled_width; - h = scaled_height; + width = scaled_width; + height = scaled_height; +#else + return VP8_STATUS_INVALID_PARAM; // rescaling not supported +#endif } } - out->width = w; - out->height = h; + buffer->width = width; + buffer->height = height; // Then, allocate buffer for real. - status = AllocateBuffer(out); + status = AllocateBuffer(buffer); if (status != VP8_STATUS_OK) return status; // Use the stride trick if vertical flip is needed. if (options != NULL && options->flip) { - status = WebPFlipBuffer(out); + status = WebPFlipBuffer(buffer); } return status; } diff --git a/3rdparty/libwebp/dec/common_dec.h b/3rdparty/libwebp/src/dec/common_dec.h similarity index 94% rename from 3rdparty/libwebp/dec/common_dec.h rename to 3rdparty/libwebp/src/dec/common_dec.h index 6961e22470..9995f1a51a 100644 --- a/3rdparty/libwebp/dec/common_dec.h +++ b/3rdparty/libwebp/src/dec/common_dec.h @@ -11,8 +11,8 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_DEC_COMMON_H_ -#define WEBP_DEC_COMMON_H_ +#ifndef WEBP_DEC_COMMON_DEC_H_ +#define WEBP_DEC_COMMON_DEC_H_ // intra prediction modes enum { B_DC_PRED = 0, // 4x4 modes @@ -51,4 +51,4 @@ enum { MB_FEATURE_TREE_PROBS = 3, NUM_PROBAS = 11 }; -#endif // WEBP_DEC_COMMON_H_ +#endif // WEBP_DEC_COMMON_DEC_H_ diff --git a/3rdparty/libwebp/dec/frame_dec.c b/3rdparty/libwebp/src/dec/frame_dec.c similarity index 98% rename from 3rdparty/libwebp/dec/frame_dec.c rename to 3rdparty/libwebp/src/dec/frame_dec.c index f91e27f7c8..517d0f5850 100644 --- a/3rdparty/libwebp/dec/frame_dec.c +++ b/3rdparty/libwebp/src/dec/frame_dec.c @@ -12,13 +12,13 @@ // Author: Skal (pascal.massimino@gmail.com) #include -#include "./vp8i_dec.h" -#include "../utils/utils.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // Main reconstruction function. -static const int kScan[16] = { +static const uint16_t kScan[16] = { 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, @@ -320,7 +320,7 @@ static void PrecomputeFilterStrengths(VP8Decoder* const dec) { #define MIN_DITHER_AMP 4 #define DITHER_AMP_TAB_SIZE 12 -static const int kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = { +static const uint8_t kQuantToDitherAmp[DITHER_AMP_TAB_SIZE] = { // roughly, it's dqm->uv_mat_[1] 8, 7, 6, 4, 4, 2, 2, 2, 1, 1, 1, 1 }; @@ -728,7 +728,7 @@ static int AllocateMemory(VP8Decoder* const dec) { } mem = (uint8_t*)dec->mem_; - dec->intra_t_ = (uint8_t*)mem; + dec->intra_t_ = mem; mem += intra_pred_mode_size; dec->yuv_t_ = (VP8TopSamples*)mem; @@ -750,7 +750,7 @@ static int AllocateMemory(VP8Decoder* const dec) { mem = (uint8_t*)WEBP_ALIGN(mem); assert((yuv_size & WEBP_ALIGN_CST) == 0); - dec->yuv_b_ = (uint8_t*)mem; + dec->yuv_b_ = mem; mem += yuv_size; dec->mb_data_ = (VP8MBData*)mem; @@ -766,7 +766,7 @@ static int AllocateMemory(VP8Decoder* const dec) { const int extra_rows = kFilterExtraRows[dec->filter_type_]; const int extra_y = extra_rows * dec->cache_y_stride_; const int extra_uv = (extra_rows / 2) * dec->cache_uv_stride_; - dec->cache_y_ = ((uint8_t*)mem) + extra_y; + dec->cache_y_ = mem + extra_y; dec->cache_u_ = dec->cache_y_ + 16 * num_caches * dec->cache_y_stride_ + extra_uv; dec->cache_v_ = dec->cache_u_ @@ -776,7 +776,7 @@ static int AllocateMemory(VP8Decoder* const dec) { mem += cache_size; // alpha plane - dec->alpha_plane_ = alpha_size ? (uint8_t*)mem : NULL; + dec->alpha_plane_ = alpha_size ? mem : NULL; mem += alpha_size; assert(mem <= (uint8_t*)dec->mem_ + dec->mem_size_); diff --git a/3rdparty/libwebp/dec/idec_dec.c b/3rdparty/libwebp/src/dec/idec_dec.c similarity index 99% rename from 3rdparty/libwebp/dec/idec_dec.c rename to 3rdparty/libwebp/src/dec/idec_dec.c index 78fb2e7186..a371ed7500 100644 --- a/3rdparty/libwebp/dec/idec_dec.c +++ b/3rdparty/libwebp/src/dec/idec_dec.c @@ -15,10 +15,10 @@ #include #include -#include "./alphai_dec.h" -#include "./webpi_dec.h" -#include "./vp8i_dec.h" -#include "../utils/utils.h" +#include "src/dec/alphai_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" // In append mode, buffer allocations increase as multiples of this value. // Needs to be a power of 2. @@ -673,12 +673,12 @@ void WebPIDelete(WebPIDecoder* idec) { //------------------------------------------------------------------------------ // Wrapper toward WebPINewDecoder -WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer, +WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE csp, uint8_t* output_buffer, size_t output_buffer_size, int output_stride) { const int is_external_memory = (output_buffer != NULL) ? 1 : 0; WebPIDecoder* idec; - if (mode >= MODE_YUV) return NULL; + if (csp >= MODE_YUV) return NULL; if (is_external_memory == 0) { // Overwrite parameters to sane values. output_buffer_size = 0; output_stride = 0; @@ -689,7 +689,7 @@ WebPIDecoder* WebPINewRGB(WEBP_CSP_MODE mode, uint8_t* output_buffer, } idec = WebPINewDecoder(NULL); if (idec == NULL) return NULL; - idec->output_.colorspace = mode; + idec->output_.colorspace = csp; idec->output_.is_external_memory = is_external_memory; idec->output_.u.RGBA.rgba = output_buffer; idec->output_.u.RGBA.stride = output_stride; diff --git a/3rdparty/libwebp/dec/io_dec.c b/3rdparty/libwebp/src/dec/io_dec.c similarity index 98% rename from 3rdparty/libwebp/dec/io_dec.c rename to 3rdparty/libwebp/src/dec/io_dec.c index 8bfab86959..e603f19c98 100644 --- a/3rdparty/libwebp/dec/io_dec.c +++ b/3rdparty/libwebp/src/dec/io_dec.c @@ -13,11 +13,11 @@ #include #include -#include "../dec/vp8i_dec.h" -#include "./webpi_dec.h" -#include "../dsp/dsp.h" -#include "../dsp/yuv.h" -#include "../utils/utils.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/dsp/dsp.h" +#include "src/dsp/yuv.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // Main YUV<->RGB conversion functions @@ -212,7 +212,7 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p, int num_rows; const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows); uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) uint8_t* alpha_dst = base_rgba; #else uint8_t* alpha_dst = base_rgba + 1; @@ -241,6 +241,7 @@ static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p, //------------------------------------------------------------------------------ // YUV rescaling (no final RGB conversion needed) +#if !defined(WEBP_REDUCE_SIZE) static int Rescale(const uint8_t* src, int src_stride, int new_lines, WebPRescaler* const wrk) { int num_lines_out = 0; @@ -431,7 +432,7 @@ static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos, int max_lines_out) { const WebPRGBABuffer* const buf = &p->output->u.RGBA; uint8_t* const base_rgba = buf->rgba + y_pos * buf->stride; -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) uint8_t* alpha_dst = base_rgba; #else uint8_t* alpha_dst = base_rgba + 1; @@ -541,6 +542,8 @@ static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) { return 1; } +#endif // WEBP_REDUCE_SIZE + //------------------------------------------------------------------------------ // Default custom functions @@ -561,10 +564,14 @@ static int CustomSetup(VP8Io* io) { WebPInitUpsamplers(); } if (io->use_scaling) { +#if !defined(WEBP_REDUCE_SIZE) const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p); if (!ok) { return 0; // memory error } +#else + return 0; // rescaling support not compiled +#endif } else { if (is_rgb) { WebPInitSamplers(); @@ -598,9 +605,6 @@ static int CustomSetup(VP8Io* io) { } } - if (is_rgb) { - VP8YUVInit(); - } return 1; } diff --git a/3rdparty/libwebp/dec/quant_dec.c b/3rdparty/libwebp/src/dec/quant_dec.c similarity index 99% rename from 3rdparty/libwebp/dec/quant_dec.c rename to 3rdparty/libwebp/src/dec/quant_dec.c index 14e3198946..f07212ad73 100644 --- a/3rdparty/libwebp/dec/quant_dec.c +++ b/3rdparty/libwebp/src/dec/quant_dec.c @@ -11,7 +11,7 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./vp8i_dec.h" +#include "src/dec/vp8i_dec.h" static WEBP_INLINE int clip(int v, int M) { return v < 0 ? 0 : v > M ? M : v; diff --git a/3rdparty/libwebp/dec/tree_dec.c b/3rdparty/libwebp/src/dec/tree_dec.c similarity index 98% rename from 3rdparty/libwebp/dec/tree_dec.c rename to 3rdparty/libwebp/src/dec/tree_dec.c index 9e805f60f3..3f5a957d32 100644 --- a/3rdparty/libwebp/dec/tree_dec.c +++ b/3rdparty/libwebp/src/dec/tree_dec.c @@ -11,15 +11,19 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./vp8i_dec.h" -#include "../utils/bit_reader_inl_utils.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/bit_reader_inl_utils.h" +#if !defined(USE_GENERIC_TREE) #if !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__) // using a table is ~1-2% slower on ARM. Prefer the coded-tree approach then. -#define USE_GENERIC_TREE +#define USE_GENERIC_TREE 1 // ALTERNATE_CODE +#else +#define USE_GENERIC_TREE 0 #endif +#endif // USE_GENERIC_TREE -#ifdef USE_GENERIC_TREE +#if (USE_GENERIC_TREE == 1) static const int8_t kYModesIntra4[18] = { -B_DC_PRED, 1, -B_TM_PRED, 2, @@ -317,7 +321,7 @@ static void ParseIntraMode(VP8BitReader* const br, int x; for (x = 0; x < 4; ++x) { const uint8_t* const prob = kBModesProba[top[x]][ymode]; -#ifdef USE_GENERIC_TREE +#if (USE_GENERIC_TREE == 1) // Generic tree-parsing int i = kYModesIntra4[VP8GetBit(br, prob[0])]; while (i > 0) { @@ -335,7 +339,7 @@ static void ParseIntraMode(VP8BitReader* const br, (!VP8GetBit(br, prob[6]) ? B_LD_PRED : (!VP8GetBit(br, prob[7]) ? B_VL_PRED : (!VP8GetBit(br, prob[8]) ? B_HD_PRED : B_HU_PRED))); -#endif // USE_GENERIC_TREE +#endif // USE_GENERIC_TREE top[x] = ymode; } memcpy(modes, top, 4 * sizeof(*top)); @@ -498,7 +502,7 @@ static const uint8_t // Paragraph 9.9 -static const int kBands[16 + 1] = { +static const uint8_t kBands[16 + 1] = { 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0 // extra entry as sentinel }; diff --git a/3rdparty/libwebp/dec/vp8_dec.c b/3rdparty/libwebp/src/dec/vp8_dec.c similarity index 99% rename from 3rdparty/libwebp/dec/vp8_dec.c rename to 3rdparty/libwebp/src/dec/vp8_dec.c index fad8d9cf35..6212efd179 100644 --- a/3rdparty/libwebp/dec/vp8_dec.c +++ b/3rdparty/libwebp/src/dec/vp8_dec.c @@ -13,12 +13,12 @@ #include -#include "./alphai_dec.h" -#include "./vp8i_dec.h" -#include "./vp8li_dec.h" -#include "./webpi_dec.h" -#include "../utils/bit_reader_inl_utils.h" -#include "../utils/utils.h" +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/bit_reader_inl_utils.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/dec/vp8_dec.h b/3rdparty/libwebp/src/dec/vp8_dec.h similarity index 94% rename from 3rdparty/libwebp/dec/vp8_dec.h rename to 3rdparty/libwebp/src/dec/vp8_dec.h index b9337bbec0..ca85b340cf 100644 --- a/3rdparty/libwebp/dec/vp8_dec.h +++ b/3rdparty/libwebp/src/dec/vp8_dec.h @@ -11,10 +11,10 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_WEBP_DECODE_VP8_H_ -#define WEBP_WEBP_DECODE_VP8_H_ +#ifndef WEBP_DEC_VP8_DEC_H_ +#define WEBP_DEC_VP8_DEC_H_ -#include "../webp/decode.h" +#include "src/webp/decode.h" #ifdef __cplusplus extern "C" { @@ -33,7 +33,7 @@ extern "C" { // /* customize io's functions (setup()/put()/teardown()) if needed. */ // // VP8Decoder* dec = VP8New(); -// bool ok = VP8Decode(dec); +// int ok = VP8Decode(dec, &io); // if (!ok) printf("Error: %s\n", VP8StatusMessage(dec)); // VP8Delete(dec); // return ok; @@ -157,24 +157,24 @@ void VP8Delete(VP8Decoder* const dec); // Miscellaneous VP8/VP8L bitstream probing functions. // Returns true if the next 3 bytes in data contain the VP8 signature. -WEBP_EXTERN(int) VP8CheckSignature(const uint8_t* const data, size_t data_size); +WEBP_EXTERN int VP8CheckSignature(const uint8_t* const data, size_t data_size); // Validates the VP8 data-header and retrieves basic header information viz // width and height. Returns 0 in case of formatting error. *width/*height // can be passed NULL. -WEBP_EXTERN(int) VP8GetInfo( +WEBP_EXTERN int VP8GetInfo( const uint8_t* data, size_t data_size, // data available so far size_t chunk_size, // total data size expected in the chunk int* const width, int* const height); // Returns true if the next byte(s) in data is a VP8L signature. -WEBP_EXTERN(int) VP8LCheckSignature(const uint8_t* const data, size_t size); +WEBP_EXTERN int VP8LCheckSignature(const uint8_t* const data, size_t size); // Validates the VP8L data-header and retrieves basic header information viz // width, height and alpha. Returns 0 in case of formatting error. // width/height/has_alpha can be passed NULL. -WEBP_EXTERN(int) VP8LGetInfo( +WEBP_EXTERN int VP8LGetInfo( const uint8_t* data, size_t data_size, // data available so far int* const width, int* const height, int* const has_alpha); @@ -182,4 +182,4 @@ WEBP_EXTERN(int) VP8LGetInfo( } // extern "C" #endif -#endif /* WEBP_WEBP_DECODE_VP8_H_ */ +#endif /* WEBP_DEC_VP8_DEC_H_ */ diff --git a/3rdparty/libwebp/dec/vp8i_dec.h b/3rdparty/libwebp/src/dec/vp8i_dec.h similarity index 97% rename from 3rdparty/libwebp/dec/vp8i_dec.h rename to 3rdparty/libwebp/src/dec/vp8i_dec.h index 555853e8f8..28244d9d7a 100644 --- a/3rdparty/libwebp/dec/vp8i_dec.h +++ b/3rdparty/libwebp/src/dec/vp8i_dec.h @@ -11,16 +11,16 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_DEC_VP8I_H_ -#define WEBP_DEC_VP8I_H_ +#ifndef WEBP_DEC_VP8I_DEC_H_ +#define WEBP_DEC_VP8I_DEC_H_ #include // for memcpy() -#include "./common_dec.h" -#include "./vp8li_dec.h" -#include "../utils/bit_reader_utils.h" -#include "../utils/random_utils.h" -#include "../utils/thread_utils.h" -#include "../dsp/dsp.h" +#include "src/dec/common_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/random_utils.h" +#include "src/utils/thread_utils.h" +#include "src/dsp/dsp.h" #ifdef __cplusplus extern "C" { @@ -32,7 +32,7 @@ extern "C" { // version numbers #define DEC_MAJ_VERSION 0 #define DEC_MIN_VERSION 6 -#define DEC_REV_VERSION 0 +#define DEC_REV_VERSION 1 // YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). // Constraints are: We need to store one 16x16 block of luma samples (y), @@ -57,7 +57,6 @@ extern "C" { // '|' = left sample, '-' = top sample, '+' = top-left sample // 't' = extra top-right sample for 4x4 modes #define YUV_SIZE (BPS * 17 + BPS * 9) -#define Y_SIZE (BPS * 17) #define Y_OFF (BPS * 1 + 8) #define U_OFF (Y_OFF + BPS * 16 + BPS) #define V_OFF (U_OFF + 16) @@ -317,4 +316,4 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec, } // extern "C" #endif -#endif /* WEBP_DEC_VP8I_H_ */ +#endif /* WEBP_DEC_VP8I_DEC_H_ */ diff --git a/3rdparty/libwebp/dec/vp8l_dec.c b/3rdparty/libwebp/src/dec/vp8l_dec.c similarity index 98% rename from 3rdparty/libwebp/dec/vp8l_dec.c rename to 3rdparty/libwebp/src/dec/vp8l_dec.c index ef359a91f0..42ea3b5e4c 100644 --- a/3rdparty/libwebp/dec/vp8l_dec.c +++ b/3rdparty/libwebp/src/dec/vp8l_dec.c @@ -14,22 +14,22 @@ #include -#include "./alphai_dec.h" -#include "./vp8li_dec.h" -#include "../dsp/dsp.h" -#include "../dsp/lossless.h" -#include "../dsp/lossless_common.h" -#include "../dsp/yuv.h" -#include "../utils/endian_inl_utils.h" -#include "../utils/huffman_utils.h" -#include "../utils/utils.h" +#include "src/dec/alphai_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/dsp/yuv.h" +#include "src/utils/endian_inl_utils.h" +#include "src/utils/huffman_utils.h" +#include "src/utils/utils.h" #define NUM_ARGB_CACHE_ROWS 16 static const int kCodeLengthLiterals = 16; static const int kCodeLengthRepeatCode = 16; -static const int kCodeLengthExtraBits[3] = { 2, 3, 7 }; -static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; +static const uint8_t kCodeLengthExtraBits[3] = { 2, 3, 7 }; +static const uint8_t kCodeLengthRepeatOffsets[3] = { 3, 3, 11 }; // ----------------------------------------------------------------------------- // Five Huffman codes are used at each meta code: @@ -86,7 +86,7 @@ static const uint8_t kCodeToPlane[CODE_TO_PLANE_CODES] = { // All values computed for 8-bit first level lookup with Mark Adler's tool: // http://www.hdfgroup.org/ftp/lib-external/zlib/zlib-1.2.5/examples/enough.c #define FIXED_TABLE_SIZE (630 * 3 + 410) -static const int kTableSize[12] = { +static const uint16_t kTableSize[12] = { FIXED_TABLE_SIZE + 654, FIXED_TABLE_SIZE + 656, FIXED_TABLE_SIZE + 658, @@ -485,6 +485,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, //------------------------------------------------------------------------------ // Scaling. +#if !defined(WEBP_REDUCE_SIZE) static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { const int num_channels = 4; const int in_width = io->mb_w; @@ -516,10 +517,13 @@ static int AllocateAndInitRescaler(VP8LDecoder* const dec, VP8Io* const io) { out_width, out_height, 0, num_channels, work); return 1; } +#endif // WEBP_REDUCE_SIZE //------------------------------------------------------------------------------ // Export to ARGB +#if !defined(WEBP_REDUCE_SIZE) + // We have special "export" function since we need to convert from BGRA static int Export(WebPRescaler* const rescaler, WEBP_CSP_MODE colorspace, int rgba_stride, uint8_t* const rgba) { @@ -561,6 +565,8 @@ static int EmitRescaledRowsRGBA(const VP8LDecoder* const dec, return num_lines_out; } +#endif // WEBP_REDUCE_SIZE + // Emit rows without any scaling. static int EmitRows(WEBP_CSP_MODE colorspace, const uint8_t* row_in, int in_stride, @@ -746,9 +752,12 @@ static void ProcessRows(VP8LDecoder* const dec, int row) { if (WebPIsRGBMode(output->colorspace)) { // convert to RGBA const WebPRGBABuffer* const buf = &output->u.RGBA; uint8_t* const rgba = buf->rgba + dec->last_out_row_ * buf->stride; - const int num_rows_out = io->use_scaling ? + const int num_rows_out = +#if !defined(WEBP_REDUCE_SIZE) + io->use_scaling ? EmitRescaledRowsRGBA(dec, rows_data, in_stride, io->mb_h, rgba, buf->stride) : +#endif // WEBP_REDUCE_SIZE EmitRows(output->colorspace, rows_data, in_stride, io->mb_w, io->mb_h, rgba, buf->stride); // Update 'last_out_row_'. @@ -1012,12 +1021,13 @@ static int DecodeAlphaData(VP8LDecoder* const dec, uint8_t* const data, ok = 0; goto End; } - assert(br->eos_ == VP8LIsEndOfStream(br)); + br->eos_ = VP8LIsEndOfStream(br); } // Process the remaining rows corresponding to last row-block. ExtractPalettedAlphaRows(dec, row > last_row ? last_row : row); End: + br->eos_ = VP8LIsEndOfStream(br); if (!ok || (br->eos_ && pos < end)) { ok = 0; dec->status_ = br->eos_ ? VP8_STATUS_SUSPENDED @@ -1090,11 +1100,12 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, VP8LFillBitWindow(br); if (htree_group->use_packed_table) { code = ReadPackedSymbols(htree_group, br, src); + if (VP8LIsEndOfStream(br)) break; if (code == PACKED_NON_LITERAL_CODE) goto AdvanceByOne; } else { code = ReadSymbol(htree_group->htrees[GREEN], br); } - if (br->eos_) break; // early out + if (VP8LIsEndOfStream(br)) break; if (code < NUM_LITERAL_CODES) { // Literal if (htree_group->is_trivial_literal) { *src = htree_group->literal_arb | (code << 8); @@ -1104,7 +1115,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, VP8LFillBitWindow(br); blue = ReadSymbol(htree_group->htrees[BLUE], br); alpha = ReadSymbol(htree_group->htrees[ALPHA], br); - if (br->eos_) break; + if (VP8LIsEndOfStream(br)) break; *src = ((uint32_t)alpha << 24) | (red << 16) | (code << 8) | blue; } AdvanceByOne: @@ -1132,7 +1143,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, VP8LFillBitWindow(br); dist_code = GetCopyDistance(dist_symbol, br); dist = PlaneCodeToDistance(width, dist_code); - if (br->eos_) break; + if (VP8LIsEndOfStream(br)) break; if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { goto Error; } else { @@ -1169,9 +1180,9 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data, } else { // Not reached goto Error; } - assert(br->eos_ == VP8LIsEndOfStream(br)); } + br->eos_ = VP8LIsEndOfStream(br); if (dec->incremental_ && br->eos_ && src < src_end) { RestoreState(dec); } else if (!br->eos_) { @@ -1630,12 +1641,19 @@ int VP8LDecodeImage(VP8LDecoder* const dec) { if (!AllocateInternalBuffers32b(dec, io->width)) goto Err; +#if !defined(WEBP_REDUCE_SIZE) if (io->use_scaling && !AllocateAndInitRescaler(dec, io)) goto Err; if (io->use_scaling || WebPIsPremultipliedMode(dec->output_->colorspace)) { // need the alpha-multiply functions for premultiplied output or rescaling WebPInitAlphaProcessing(); } +#else + if (io->use_scaling) { + dec->status_ = VP8_STATUS_INVALID_PARAM; + goto Err; + } +#endif if (!WebPIsRGBMode(dec->output_->colorspace)) { WebPInitConvertARGBToYUV(); if (dec->output_->u.YUVA.a != NULL) WebPInitAlphaProcessing(); diff --git a/3rdparty/libwebp/dec/vp8li_dec.h b/3rdparty/libwebp/src/dec/vp8li_dec.h similarity index 94% rename from 3rdparty/libwebp/dec/vp8li_dec.h rename to 3rdparty/libwebp/src/dec/vp8li_dec.h index 097a9d0589..8e500cf9ff 100644 --- a/3rdparty/libwebp/dec/vp8li_dec.h +++ b/3rdparty/libwebp/src/dec/vp8li_dec.h @@ -12,14 +12,14 @@ // Author: Skal (pascal.massimino@gmail.com) // Vikas Arora(vikaas.arora@gmail.com) -#ifndef WEBP_DEC_VP8LI_H_ -#define WEBP_DEC_VP8LI_H_ +#ifndef WEBP_DEC_VP8LI_DEC_H_ +#define WEBP_DEC_VP8LI_DEC_H_ #include // for memcpy() -#include "./webpi_dec.h" -#include "../utils/bit_reader_utils.h" -#include "../utils/color_cache_utils.h" -#include "../utils/huffman_utils.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/huffman_utils.h" #ifdef __cplusplus extern "C" { @@ -132,4 +132,4 @@ void VP8LDelete(VP8LDecoder* const dec); } // extern "C" #endif -#endif /* WEBP_DEC_VP8LI_H_ */ +#endif /* WEBP_DEC_VP8LI_DEC_H_ */ diff --git a/3rdparty/libwebp/dec/webp_dec.c b/3rdparty/libwebp/src/dec/webp_dec.c similarity index 98% rename from 3rdparty/libwebp/dec/webp_dec.c rename to 3rdparty/libwebp/src/dec/webp_dec.c index a8e9c2c510..42d098874d 100644 --- a/3rdparty/libwebp/dec/webp_dec.c +++ b/3rdparty/libwebp/src/dec/webp_dec.c @@ -13,11 +13,11 @@ #include -#include "./vp8i_dec.h" -#include "./vp8li_dec.h" -#include "./webpi_dec.h" -#include "../utils/utils.h" -#include "../webp/mux_types.h" // ALPHA_FLAG +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/dec/webpi_dec.h" +#include "src/utils/utils.h" +#include "src/webp/mux_types.h" // ALPHA_FLAG //------------------------------------------------------------------------------ // RIFF layout is: @@ -421,7 +421,9 @@ VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers) { NULL, NULL, NULL, &has_animation, NULL, headers); if (status == VP8_STATUS_OK || status == VP8_STATUS_NOT_ENOUGH_DATA) { - // TODO(jzern): full support of animation frames will require API additions. + // The WebPDemux API + libwebp can be used to decode individual + // uncomposited frames or the WebPAnimDecoder can be used to fully + // reconstruct them (see webp/demux.h). if (has_animation) { status = VP8_STATUS_UNSUPPORTED_FEATURE; } diff --git a/3rdparty/libwebp/dec/webpi_dec.h b/3rdparty/libwebp/src/dec/webpi_dec.h similarity index 97% rename from 3rdparty/libwebp/dec/webpi_dec.h rename to 3rdparty/libwebp/src/dec/webpi_dec.h index 696abc1958..c378ba6fc3 100644 --- a/3rdparty/libwebp/dec/webpi_dec.h +++ b/3rdparty/libwebp/src/dec/webpi_dec.h @@ -11,15 +11,15 @@ // // Author: somnath@google.com (Somnath Banerjee) -#ifndef WEBP_DEC_WEBPI_H_ -#define WEBP_DEC_WEBPI_H_ +#ifndef WEBP_DEC_WEBPI_DEC_H_ +#define WEBP_DEC_WEBPI_DEC_H_ #ifdef __cplusplus extern "C" { #endif -#include "../utils/rescaler_utils.h" -#include "./vp8_dec.h" +#include "src/utils/rescaler_utils.h" +#include "src/dec/vp8_dec.h" //------------------------------------------------------------------------------ // WebPDecParams: Decoding output parameters. Transient internal object. @@ -130,4 +130,4 @@ int WebPAvoidSlowMemory(const WebPDecBuffer* const output, } // extern "C" #endif -#endif /* WEBP_DEC_WEBPI_H_ */ +#endif /* WEBP_DEC_WEBPI_DEC_H_ */ diff --git a/3rdparty/libwebp/demux/anim_decode.c b/3rdparty/libwebp/src/demux/anim_decode.c similarity index 99% rename from 3rdparty/libwebp/demux/anim_decode.c rename to 3rdparty/libwebp/src/demux/anim_decode.c index f1cf176e72..05dd707371 100644 --- a/3rdparty/libwebp/demux/anim_decode.c +++ b/3rdparty/libwebp/src/demux/anim_decode.c @@ -11,15 +11,15 @@ // #ifdef HAVE_CONFIG_H -#include "../webp/config.h" +#include "src/webp/config.h" #endif #include #include -#include "../utils/utils.h" -#include "../webp/decode.h" -#include "../webp/demux.h" +#include "src/utils/utils.h" +#include "src/webp/decode.h" +#include "src/webp/demux.h" #define NUM_CHANNELS 4 diff --git a/3rdparty/libwebp/demux/demux.c b/3rdparty/libwebp/src/demux/demux.c similarity index 98% rename from 3rdparty/libwebp/demux/demux.c rename to 3rdparty/libwebp/src/demux/demux.c index 100eab8c01..79c24a5a7f 100644 --- a/3rdparty/libwebp/demux/demux.c +++ b/3rdparty/libwebp/src/demux/demux.c @@ -11,21 +11,21 @@ // #ifdef HAVE_CONFIG_H -#include "../webp/config.h" +#include "src/webp/config.h" #endif #include #include #include -#include "../utils/utils.h" -#include "../webp/decode.h" // WebPGetFeatures -#include "../webp/demux.h" -#include "../webp/format_constants.h" +#include "src/utils/utils.h" +#include "src/webp/decode.h" // WebPGetFeatures +#include "src/webp/demux.h" +#include "src/webp/format_constants.h" #define DMUX_MAJ_VERSION 0 #define DMUX_MIN_VERSION 3 -#define DMUX_REV_VERSION 2 +#define DMUX_REV_VERSION 3 typedef struct { size_t start_; // start location of the data @@ -205,12 +205,14 @@ static void SetFrameInfo(size_t start_offset, size_t size, frame->complete_ = complete; } -// Store image bearing chunks to 'frame'. +// Store image bearing chunks to 'frame'. 'min_size' is an optional size +// requirement, it may be zero. static ParseStatus StoreFrame(int frame_num, uint32_t min_size, MemBuffer* const mem, Frame* const frame) { int alpha_chunks = 0; int image_chunks = 0; - int done = (MemDataSize(mem) < min_size); + int done = (MemDataSize(mem) < CHUNK_HEADER_SIZE || + MemDataSize(mem) < min_size); ParseStatus status = PARSE_OK; if (done) return PARSE_NEED_MORE_DATA; @@ -401,9 +403,9 @@ static ParseStatus ParseSingleImage(WebPDemuxer* const dmux) { frame = (Frame*)WebPSafeCalloc(1ULL, sizeof(*frame)); if (frame == NULL) return PARSE_ERROR; - // For the single image case we allow parsing of a partial frame, but we need - // at least CHUNK_HEADER_SIZE for parsing. - status = StoreFrame(1, CHUNK_HEADER_SIZE, &dmux->mem_, frame); + // For the single image case we allow parsing of a partial frame, so no + // minimum size is imposed here. + status = StoreFrame(1, 0, &dmux->mem_, frame); if (status != PARSE_ERROR) { const int has_alpha = !!(dmux->feature_flags_ & ALPHA_FLAG); // Clear any alpha when the alpha flag is missing. diff --git a/3rdparty/libwebp/dsp/alpha_processing.c b/3rdparty/libwebp/src/dsp/alpha_processing.c similarity index 83% rename from 3rdparty/libwebp/dsp/alpha_processing.c rename to 3rdparty/libwebp/src/dsp/alpha_processing.c index 4b60e092be..590e3bc312 100644 --- a/3rdparty/libwebp/dsp/alpha_processing.c +++ b/3rdparty/libwebp/src/dsp/alpha_processing.c @@ -12,10 +12,13 @@ // Author: Skal (pascal.massimino@gmail.com) #include -#include "./dsp.h" +#include "src/dsp/dsp.h" // Tables can be faster on some platform but incur some extra binary size (~2k). -// #define USE_TABLES_FOR_ALPHA_MULT +#if !defined(USE_TABLES_FOR_ALPHA_MULT) +#define USE_TABLES_FOR_ALPHA_MULT 0 // ALTERNATE_CODE +#endif + // ----------------------------------------------------------------------------- @@ -29,7 +32,7 @@ static uint32_t Mult(uint8_t x, uint32_t mult) { return v; } -#ifdef USE_TABLES_FOR_ALPHA_MULT +#if (USE_TABLES_FOR_ALPHA_MULT == 1) static const uint32_t kMultTables[2][256] = { { // (255u << MFIX) / alpha @@ -132,9 +135,9 @@ static WEBP_INLINE uint32_t GetScale(uint32_t a, int inverse) { return inverse ? (255u << MFIX) / a : a * KINV_255; } -#endif // USE_TABLES_FOR_ALPHA_MULT +#endif // USE_TABLES_FOR_ALPHA_MULT -void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse) { +void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse) { int x; for (x = 0; x < width; ++x) { const uint32_t argb = ptr[x]; @@ -154,8 +157,8 @@ void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse) { } } -void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse) { +void WebPMultRow_C(uint8_t* const ptr, const uint8_t* const alpha, + int width, int inverse) { int x; for (x = 0; x < width; ++x) { const uint32_t a = alpha[x]; @@ -217,8 +220,9 @@ void WebPMultRows(uint8_t* ptr, int stride, #define PREMULTIPLY(x, m) (((x) * (m) + (1U << 23)) >> 24) #endif -static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first, - int w, int h, int stride) { +#if !WEBP_NEON_OMIT_C_CODE +static void ApplyAlphaMultiply_C(uint8_t* rgba, int alpha_first, + int w, int h, int stride) { while (h-- > 0) { uint8_t* const rgb = rgba + (alpha_first ? 1 : 0); const uint8_t* const alpha = rgba + (alpha_first ? 0 : 3); @@ -235,6 +239,7 @@ static void ApplyAlphaMultiply(uint8_t* rgba, int alpha_first, rgba += stride; } } +#endif // !WEBP_NEON_OMIT_C_CODE #undef MULTIPLIER #undef PREMULTIPLY @@ -254,9 +259,9 @@ static WEBP_INLINE uint8_t multiply(uint8_t x, uint32_t m) { return (x * m) >> 16; } -static WEBP_INLINE void ApplyAlphaMultiply4444(uint8_t* rgba4444, - int w, int h, int stride, - int rg_byte_pos /* 0 or 1 */) { +static WEBP_INLINE void ApplyAlphaMultiply4444_C(uint8_t* rgba4444, + int w, int h, int stride, + int rg_byte_pos /* 0 or 1 */) { while (h-- > 0) { int i; for (i = 0; i < w; ++i) { @@ -275,15 +280,16 @@ static WEBP_INLINE void ApplyAlphaMultiply4444(uint8_t* rgba4444, } #undef MULTIPLIER -static void ApplyAlphaMultiply_16b(uint8_t* rgba4444, - int w, int h, int stride) { -#ifdef WEBP_SWAP_16BIT_CSP - ApplyAlphaMultiply4444(rgba4444, w, h, stride, 1); +static void ApplyAlphaMultiply_16b_C(uint8_t* rgba4444, + int w, int h, int stride) { +#if (WEBP_SWAP_16BIT_CSP == 1) + ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 1); #else - ApplyAlphaMultiply4444(rgba4444, w, h, stride, 0); + ApplyAlphaMultiply4444_C(rgba4444, w, h, stride, 0); #endif } +#if !WEBP_NEON_OMIT_C_CODE static int DispatchAlpha_C(const uint8_t* alpha, int alpha_stride, int width, int height, uint8_t* dst, int dst_stride) { @@ -338,6 +344,36 @@ static void ExtractGreen_C(const uint32_t* argb, uint8_t* alpha, int size) { int i; for (i = 0; i < size; ++i) alpha[i] = argb[i] >> 8; } +#endif // !WEBP_NEON_OMIT_C_CODE + +//------------------------------------------------------------------------------ + +static int HasAlpha8b_C(const uint8_t* src, int length) { + while (length-- > 0) if (*src++ != 0xff) return 1; + return 0; +} + +static int HasAlpha32b_C(const uint8_t* src, int length) { + int x; + for (x = 0; length-- > 0; x += 4) if (src[x] != 0xff) return 1; + return 0; +} + +//------------------------------------------------------------------------------ +// Simple channel manipulations. + +static WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) { + return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b); +} + +static void PackRGB_C(const uint8_t* r, const uint8_t* g, const uint8_t* b, + int len, int step, uint32_t* out) { + int i, offset = 0; + for (i = 0; i < len; ++i) { + out[i] = MakeARGB32(0xff, r[offset], g[offset], b[offset]); + offset += step; + } +} void (*WebPApplyAlphaMultiply)(uint8_t*, int, int, int, int); void (*WebPApplyAlphaMultiply4444)(uint8_t*, int, int, int); @@ -345,6 +381,11 @@ int (*WebPDispatchAlpha)(const uint8_t*, int, int, int, uint8_t*, int); void (*WebPDispatchAlphaToGreen)(const uint8_t*, int, int, int, uint32_t*, int); int (*WebPExtractAlpha)(const uint8_t*, int, int, int, uint8_t*, int); void (*WebPExtractGreen)(const uint32_t* argb, uint8_t* alpha, int size); +void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b, + int len, int step, uint32_t* out); + +int (*WebPHasAlpha8b)(const uint8_t* src, int length); +int (*WebPHasAlpha32b)(const uint8_t* src, int length); //------------------------------------------------------------------------------ // Init function @@ -360,15 +401,21 @@ static volatile VP8CPUInfo alpha_processing_last_cpuinfo_used = WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) { if (alpha_processing_last_cpuinfo_used == VP8GetCPUInfo) return; - WebPMultARGBRow = WebPMultARGBRowC; - WebPMultRow = WebPMultRowC; - WebPApplyAlphaMultiply = ApplyAlphaMultiply; - WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b; + WebPMultARGBRow = WebPMultARGBRow_C; + WebPMultRow = WebPMultRow_C; + WebPApplyAlphaMultiply4444 = ApplyAlphaMultiply_16b_C; + WebPPackRGB = PackRGB_C; +#if !WEBP_NEON_OMIT_C_CODE + WebPApplyAlphaMultiply = ApplyAlphaMultiply_C; WebPDispatchAlpha = DispatchAlpha_C; WebPDispatchAlphaToGreen = DispatchAlphaToGreen_C; WebPExtractAlpha = ExtractAlpha_C; WebPExtractGreen = ExtractGreen_C; +#endif + + WebPHasAlpha8b = HasAlpha8b_C; + WebPHasAlpha32b = HasAlpha32b_C; // If defined, use CPUInfo() to overwrite some pointers with faster versions. if (VP8GetCPUInfo != NULL) { @@ -382,16 +429,31 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessing(void) { #endif } #endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - WebPInitAlphaProcessingNEON(); - } -#endif #if defined(WEBP_USE_MIPS_DSP_R2) if (VP8GetCPUInfo(kMIPSdspR2)) { WebPInitAlphaProcessingMIPSdspR2(); } #endif } + +#if defined(WEBP_USE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPInitAlphaProcessingNEON(); + } +#endif + + assert(WebPMultARGBRow != NULL); + assert(WebPMultRow != NULL); + assert(WebPApplyAlphaMultiply != NULL); + assert(WebPApplyAlphaMultiply4444 != NULL); + assert(WebPDispatchAlpha != NULL); + assert(WebPDispatchAlphaToGreen != NULL); + assert(WebPExtractAlpha != NULL); + assert(WebPExtractGreen != NULL); + assert(WebPPackRGB != NULL); + assert(WebPHasAlpha8b != NULL); + assert(WebPHasAlpha32b != NULL); + alpha_processing_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/3rdparty/libwebp/dsp/alpha_processing_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c similarity index 69% rename from 3rdparty/libwebp/dsp/alpha_processing_mips_dsp_r2.c rename to 3rdparty/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c index c631d78905..e0dc91bab9 100644 --- a/3rdparty/libwebp/dsp/alpha_processing_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/alpha_processing_mips_dsp_r2.c @@ -12,13 +12,13 @@ // Author(s): Branimir Vasic (branimir.vasic@imgtec.com) // Djordje Pesut (djordje.pesut@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS_DSP_R2) -static int DispatchAlpha(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint8_t* dst, int dst_stride) { +static int DispatchAlpha_MIPSdspR2(const uint8_t* alpha, int alpha_stride, + int width, int height, + uint8_t* dst, int dst_stride) { uint32_t alpha_mask = 0xffffffff; int i, j, temp0; @@ -79,7 +79,8 @@ static int DispatchAlpha(const uint8_t* alpha, int alpha_stride, return (alpha_mask != 0xff); } -static void MultARGBRow(uint32_t* const ptr, int width, int inverse) { +static void MultARGBRow_MIPSdspR2(uint32_t* const ptr, int width, + int inverse) { int x; const uint32_t c_00ffffff = 0x00ffffffu; const uint32_t c_ff000000 = 0xff000000u; @@ -124,14 +125,54 @@ static void MultARGBRow(uint32_t* const ptr, int width, int inverse) { } } +static void PackRGB_MIPSdspR2(const uint8_t* r, const uint8_t* g, + const uint8_t* b, int len, int step, + uint32_t* out) { + int temp0, temp1, temp2, offset; + const int rest = len & 1; + const int a = 0xff; + const uint32_t* const loop_end = out + len - rest; + __asm__ volatile ( + "xor %[offset], %[offset], %[offset] \n\t" + "beq %[loop_end], %[out], 0f \n\t" + "2: \n\t" + "lbux %[temp0], %[offset](%[r]) \n\t" + "lbux %[temp1], %[offset](%[g]) \n\t" + "lbux %[temp2], %[offset](%[b]) \n\t" + "ins %[temp0], %[a], 16, 16 \n\t" + "ins %[temp2], %[temp1], 16, 16 \n\t" + "addiu %[out], %[out], 4 \n\t" + "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t" + "sw %[temp0], -4(%[out]) \n\t" + "addu %[offset], %[offset], %[step] \n\t" + "bne %[loop_end], %[out], 2b \n\t" + "0: \n\t" + "beq %[rest], $zero, 1f \n\t" + "lbux %[temp0], %[offset](%[r]) \n\t" + "lbux %[temp1], %[offset](%[g]) \n\t" + "lbux %[temp2], %[offset](%[b]) \n\t" + "ins %[temp0], %[a], 16, 16 \n\t" + "ins %[temp2], %[temp1], 16, 16 \n\t" + "precr.qb.ph %[temp0], %[temp0], %[temp2] \n\t" + "sw %[temp0], 0(%[out]) \n\t" + "1: \n\t" + : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1), [temp2]"=&r"(temp2), + [offset]"=&r"(offset), [out]"+&r"(out) + : [a]"r"(a), [r]"r"(r), [g]"r"(g), [b]"r"(b), [step]"r"(step), + [loop_end]"r"(loop_end), [rest]"r"(rest) + : "memory" + ); +} + //------------------------------------------------------------------------------ // Entry point extern void WebPInitAlphaProcessingMIPSdspR2(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingMIPSdspR2(void) { - WebPDispatchAlpha = DispatchAlpha; - WebPMultARGBRow = MultARGBRow; + WebPDispatchAlpha = DispatchAlpha_MIPSdspR2; + WebPMultARGBRow = MultARGBRow_MIPSdspR2; + WebPPackRGB = PackRGB_MIPSdspR2; } #else // !WEBP_USE_MIPS_DSP_R2 diff --git a/3rdparty/libwebp/dsp/alpha_processing_neon.c b/3rdparty/libwebp/src/dsp/alpha_processing_neon.c similarity index 99% rename from 3rdparty/libwebp/dsp/alpha_processing_neon.c rename to 3rdparty/libwebp/src/dsp/alpha_processing_neon.c index 606a401cf7..9d55421704 100644 --- a/3rdparty/libwebp/dsp/alpha_processing_neon.c +++ b/3rdparty/libwebp/src/dsp/alpha_processing_neon.c @@ -11,11 +11,11 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_NEON) -#include "./neon.h" +#include "src/dsp/neon.h" //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/dsp/alpha_processing_sse2.c b/3rdparty/libwebp/src/dsp/alpha_processing_sse2.c similarity index 76% rename from 3rdparty/libwebp/dsp/alpha_processing_sse2.c rename to 3rdparty/libwebp/src/dsp/alpha_processing_sse2.c index 83dc559fac..76587006a1 100644 --- a/3rdparty/libwebp/dsp/alpha_processing_sse2.c +++ b/3rdparty/libwebp/src/dsp/alpha_processing_sse2.c @@ -11,16 +11,16 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE2) #include //------------------------------------------------------------------------------ -static int DispatchAlpha(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint8_t* dst, int dst_stride) { +static int DispatchAlpha_SSE2(const uint8_t* alpha, int alpha_stride, + int width, int height, + uint8_t* dst, int dst_stride) { // alpha_and stores an 'and' operation of all the alpha[] values. The final // value is not 0xff if any of the alpha[] is not equal to 0xff. uint32_t alpha_and = 0xff; @@ -72,9 +72,9 @@ static int DispatchAlpha(const uint8_t* alpha, int alpha_stride, return (alpha_and != 0xff); } -static void DispatchAlphaToGreen(const uint8_t* alpha, int alpha_stride, - int width, int height, - uint32_t* dst, int dst_stride) { +static void DispatchAlphaToGreen_SSE2(const uint8_t* alpha, int alpha_stride, + int width, int height, + uint32_t* dst, int dst_stride) { int i, j; const __m128i zero = _mm_setzero_si128(); const int limit = width & ~15; @@ -98,9 +98,9 @@ static void DispatchAlphaToGreen(const uint8_t* alpha, int alpha_stride, } } -static int ExtractAlpha(const uint8_t* argb, int argb_stride, - int width, int height, - uint8_t* alpha, int alpha_stride) { +static int ExtractAlpha_SSE2(const uint8_t* argb, int argb_stride, + int width, int height, + uint8_t* alpha, int alpha_stride) { // alpha_and stores an 'and' operation of all the alpha[] values. The final // value is not 0xff if any of the alpha[] is not equal to 0xff. uint32_t alpha_and = 0xff; @@ -210,6 +210,61 @@ static void ApplyAlphaMultiply_SSE2(uint8_t* rgba, int alpha_first, #undef MULTIPLIER #undef PREMULTIPLY +//------------------------------------------------------------------------------ +// Alpha detection + +static int HasAlpha8b_SSE2(const uint8_t* src, int length) { + const __m128i all_0xff = _mm_set1_epi8(0xff); + int i = 0; + for (; i + 16 <= length; i += 16) { + const __m128i v = _mm_loadu_si128((const __m128i*)(src + i)); + const __m128i bits = _mm_cmpeq_epi8(v, all_0xff); + const int mask = _mm_movemask_epi8(bits); + if (mask != 0xffff) return 1; + } + for (; i < length; ++i) if (src[i] != 0xff) return 1; + return 0; +} + +static int HasAlpha32b_SSE2(const uint8_t* src, int length) { + const __m128i alpha_mask = _mm_set1_epi32(0xff); + const __m128i all_0xff = _mm_set1_epi8(0xff); + int i = 0; + // We don't know if we can access the last 3 bytes after the last alpha + // value 'src[4 * length - 4]' (because we don't know if alpha is the first + // or the last byte of the quadruplet). Hence the '-3' protection below. + length = length * 4 - 3; // size in bytes + for (; i + 64 <= length; i += 64) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)(src + i + 0)); + const __m128i a1 = _mm_loadu_si128((const __m128i*)(src + i + 16)); + const __m128i a2 = _mm_loadu_si128((const __m128i*)(src + i + 32)); + const __m128i a3 = _mm_loadu_si128((const __m128i*)(src + i + 48)); + const __m128i b0 = _mm_and_si128(a0, alpha_mask); + const __m128i b1 = _mm_and_si128(a1, alpha_mask); + const __m128i b2 = _mm_and_si128(a2, alpha_mask); + const __m128i b3 = _mm_and_si128(a3, alpha_mask); + const __m128i c0 = _mm_packs_epi32(b0, b1); + const __m128i c1 = _mm_packs_epi32(b2, b3); + const __m128i d = _mm_packus_epi16(c0, c1); + const __m128i bits = _mm_cmpeq_epi8(d, all_0xff); + const int mask = _mm_movemask_epi8(bits); + if (mask != 0xffff) return 1; + } + for (; i + 32 <= length; i += 32) { + const __m128i a0 = _mm_loadu_si128((const __m128i*)(src + i + 0)); + const __m128i a1 = _mm_loadu_si128((const __m128i*)(src + i + 16)); + const __m128i b0 = _mm_and_si128(a0, alpha_mask); + const __m128i b1 = _mm_and_si128(a1, alpha_mask); + const __m128i c = _mm_packs_epi32(b0, b1); + const __m128i d = _mm_packus_epi16(c, c); + const __m128i bits = _mm_cmpeq_epi8(d, all_0xff); + const int mask = _mm_movemask_epi8(bits); + if (mask != 0xffff) return 1; + } + for (; i <= length; i += 4) if (src[i] != 0xff) return 1; + return 0; +} + // ----------------------------------------------------------------------------- // Apply alpha value to rows @@ -238,7 +293,7 @@ static void MultARGBRow_SSE2(uint32_t* const ptr, int width, int inverse) { } } width -= x; - if (width > 0) WebPMultARGBRowC(ptr + x, width, inverse); + if (width > 0) WebPMultARGBRow_C(ptr + x, width, inverse); } static void MultRow_SSE2(uint8_t* const ptr, const uint8_t* const alpha, @@ -261,7 +316,7 @@ static void MultRow_SSE2(uint8_t* const ptr, const uint8_t* const alpha, } } width -= x; - if (width > 0) WebPMultRowC(ptr + x, alpha + x, width, inverse); + if (width > 0) WebPMultRow_C(ptr + x, alpha + x, width, inverse); } //------------------------------------------------------------------------------ @@ -273,9 +328,12 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE2(void) { WebPMultARGBRow = MultARGBRow_SSE2; WebPMultRow = MultRow_SSE2; WebPApplyAlphaMultiply = ApplyAlphaMultiply_SSE2; - WebPDispatchAlpha = DispatchAlpha; - WebPDispatchAlphaToGreen = DispatchAlphaToGreen; - WebPExtractAlpha = ExtractAlpha; + WebPDispatchAlpha = DispatchAlpha_SSE2; + WebPDispatchAlphaToGreen = DispatchAlphaToGreen_SSE2; + WebPExtractAlpha = ExtractAlpha_SSE2; + + WebPHasAlpha8b = HasAlpha8b_SSE2; + WebPHasAlpha32b = HasAlpha32b_SSE2; } #else // !WEBP_USE_SSE2 diff --git a/3rdparty/libwebp/dsp/alpha_processing_sse41.c b/3rdparty/libwebp/src/dsp/alpha_processing_sse41.c similarity index 93% rename from 3rdparty/libwebp/dsp/alpha_processing_sse41.c rename to 3rdparty/libwebp/src/dsp/alpha_processing_sse41.c index 986fde94ed..56040f9c88 100644 --- a/3rdparty/libwebp/dsp/alpha_processing_sse41.c +++ b/3rdparty/libwebp/src/dsp/alpha_processing_sse41.c @@ -11,7 +11,7 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE41) @@ -19,9 +19,9 @@ //------------------------------------------------------------------------------ -static int ExtractAlpha(const uint8_t* argb, int argb_stride, - int width, int height, - uint8_t* alpha, int alpha_stride) { +static int ExtractAlpha_SSE41(const uint8_t* argb, int argb_stride, + int width, int height, + uint8_t* alpha, int alpha_stride) { // alpha_and stores an 'and' operation of all the alpha[] values. The final // value is not 0xff if any of the alpha[] is not equal to 0xff. uint32_t alpha_and = 0xff; @@ -82,7 +82,7 @@ static int ExtractAlpha(const uint8_t* argb, int argb_stride, extern void WebPInitAlphaProcessingSSE41(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitAlphaProcessingSSE41(void) { - WebPExtractAlpha = ExtractAlpha; + WebPExtractAlpha = ExtractAlpha_SSE41; } #else // !WEBP_USE_SSE41 diff --git a/3rdparty/libwebp/dsp/argb.c b/3rdparty/libwebp/src/dsp/argb.c similarity index 100% rename from 3rdparty/libwebp/dsp/argb.c rename to 3rdparty/libwebp/src/dsp/argb.c diff --git a/3rdparty/libwebp/dsp/argb_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/argb_mips_dsp_r2.c similarity index 100% rename from 3rdparty/libwebp/dsp/argb_mips_dsp_r2.c rename to 3rdparty/libwebp/src/dsp/argb_mips_dsp_r2.c diff --git a/3rdparty/libwebp/dsp/argb_sse2.c b/3rdparty/libwebp/src/dsp/argb_sse2.c similarity index 94% rename from 3rdparty/libwebp/dsp/argb_sse2.c rename to 3rdparty/libwebp/src/dsp/argb_sse2.c index afcb1957e7..17dd596c0e 100644 --- a/3rdparty/libwebp/dsp/argb_sse2.c +++ b/3rdparty/libwebp/src/dsp/argb_sse2.c @@ -57,6 +57,9 @@ static void PackARGB(const uint8_t* a, const uint8_t* r, const uint8_t* g, extern void VP8EncDspARGBInitSSE2(void); WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspARGBInitSSE2(void) { + extern void (*VP8PackARGB)(const uint8_t*, const uint8_t*, const uint8_t*, + const uint8_t*, int, uint32_t*); + VP8PackARGB = PackARGB; } diff --git a/3rdparty/libwebp/dsp/common_sse2.h b/3rdparty/libwebp/src/dsp/common_sse2.h similarity index 100% rename from 3rdparty/libwebp/dsp/common_sse2.h rename to 3rdparty/libwebp/src/dsp/common_sse2.h diff --git a/3rdparty/libwebp/dsp/cost.c b/3rdparty/libwebp/src/dsp/cost.c similarity index 98% rename from 3rdparty/libwebp/dsp/cost.c rename to 3rdparty/libwebp/src/dsp/cost.c index 58ddea7248..a732389d58 100644 --- a/3rdparty/libwebp/dsp/cost.c +++ b/3rdparty/libwebp/src/dsp/cost.c @@ -9,8 +9,8 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" -#include "../enc/cost_enc.h" +#include "src/dsp/dsp.h" +#include "src/enc/cost_enc.h" //------------------------------------------------------------------------------ // Boolean-cost cost table @@ -319,7 +319,7 @@ const uint8_t VP8EncBands[16 + 1] = { //------------------------------------------------------------------------------ // Mode costs -static int GetResidualCost(int ctx0, const VP8Residual* const res) { +static int GetResidualCost_C(int ctx0, const VP8Residual* const res) { int n = res->first; // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 const int p0 = res->prob[n][ctx0][0]; @@ -354,8 +354,8 @@ static int GetResidualCost(int ctx0, const VP8Residual* const res) { return cost; } -static void SetResidualCoeffs(const int16_t* const coeffs, - VP8Residual* const res) { +static void SetResidualCoeffs_C(const int16_t* const coeffs, + VP8Residual* const res) { int n; res->last = -1; assert(res->first == 0 || coeffs[0] == 0); @@ -384,8 +384,8 @@ static volatile VP8CPUInfo cost_last_cpuinfo_used = WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInit(void) { if (cost_last_cpuinfo_used == VP8GetCPUInfo) return; - VP8GetResidualCost = GetResidualCost; - VP8SetResidualCoeffs = SetResidualCoeffs; + VP8GetResidualCost = GetResidualCost_C; + VP8SetResidualCoeffs = SetResidualCoeffs_C; // If defined, use CPUInfo() to overwrite some pointers with faster versions. if (VP8GetCPUInfo != NULL) { diff --git a/3rdparty/libwebp/dsp/cost_mips32.c b/3rdparty/libwebp/src/dsp/cost_mips32.c similarity index 95% rename from 3rdparty/libwebp/dsp/cost_mips32.c rename to 3rdparty/libwebp/src/dsp/cost_mips32.c index 3102da877a..0500f88c13 100644 --- a/3rdparty/libwebp/dsp/cost_mips32.c +++ b/3rdparty/libwebp/src/dsp/cost_mips32.c @@ -9,13 +9,13 @@ // // Author: Djordje Pesut (djordje.pesut@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS32) -#include "../enc/cost_enc.h" +#include "src/enc/cost_enc.h" -static int GetResidualCost(int ctx0, const VP8Residual* const res) { +static int GetResidualCost_MIPS32(int ctx0, const VP8Residual* const res) { int temp0, temp1; int v_reg, ctx_reg; int n = res->first; @@ -96,8 +96,8 @@ static int GetResidualCost(int ctx0, const VP8Residual* const res) { return cost; } -static void SetResidualCoeffs(const int16_t* const coeffs, - VP8Residual* const res) { +static void SetResidualCoeffs_MIPS32(const int16_t* const coeffs, + VP8Residual* const res) { const int16_t* p_coeffs = (int16_t*)coeffs; int temp0, temp1, temp2, n, n1; assert(res->first == 0 || coeffs[0] == 0); @@ -143,8 +143,8 @@ static void SetResidualCoeffs(const int16_t* const coeffs, extern void VP8EncDspCostInitMIPS32(void); WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPS32(void) { - VP8GetResidualCost = GetResidualCost; - VP8SetResidualCoeffs = SetResidualCoeffs; + VP8GetResidualCost = GetResidualCost_MIPS32; + VP8SetResidualCoeffs = SetResidualCoeffs_MIPS32; } #else // !WEBP_USE_MIPS32 diff --git a/3rdparty/libwebp/dsp/cost_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/cost_mips_dsp_r2.c similarity index 96% rename from 3rdparty/libwebp/dsp/cost_mips_dsp_r2.c rename to 3rdparty/libwebp/src/dsp/cost_mips_dsp_r2.c index 6ec8aeb610..51248de7a1 100644 --- a/3rdparty/libwebp/dsp/cost_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/cost_mips_dsp_r2.c @@ -9,13 +9,13 @@ // // Author: Djordje Pesut (djordje.pesut@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS_DSP_R2) -#include "../enc/cost_enc.h" +#include "src/enc/cost_enc.h" -static int GetResidualCost(int ctx0, const VP8Residual* const res) { +static int GetResidualCost_MIPSdspR2(int ctx0, const VP8Residual* const res) { int temp0, temp1; int v_reg, ctx_reg; int n = res->first; @@ -97,7 +97,7 @@ static int GetResidualCost(int ctx0, const VP8Residual* const res) { extern void VP8EncDspCostInitMIPSdspR2(void); WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitMIPSdspR2(void) { - VP8GetResidualCost = GetResidualCost; + VP8GetResidualCost = GetResidualCost_MIPSdspR2; } #else // !WEBP_USE_MIPS_DSP_R2 diff --git a/3rdparty/libwebp/dsp/cost_sse2.c b/3rdparty/libwebp/src/dsp/cost_sse2.c similarity index 90% rename from 3rdparty/libwebp/dsp/cost_sse2.c rename to 3rdparty/libwebp/src/dsp/cost_sse2.c index 421d51fdd5..487a079921 100644 --- a/3rdparty/libwebp/dsp/cost_sse2.c +++ b/3rdparty/libwebp/src/dsp/cost_sse2.c @@ -11,19 +11,19 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE2) #include -#include "../enc/cost_enc.h" -#include "../enc/vp8i_enc.h" -#include "../utils/utils.h" +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ -static void SetResidualCoeffsSSE2(const int16_t* const coeffs, - VP8Residual* const res) { +static void SetResidualCoeffs_SSE2(const int16_t* const coeffs, + VP8Residual* const res) { const __m128i c0 = _mm_loadu_si128((const __m128i*)(coeffs + 0)); const __m128i c1 = _mm_loadu_si128((const __m128i*)(coeffs + 8)); // Use SSE2 to compare 16 values with a single instruction. @@ -42,7 +42,7 @@ static void SetResidualCoeffsSSE2(const int16_t* const coeffs, res->coeffs = coeffs; } -static int GetResidualCostSSE2(int ctx0, const VP8Residual* const res) { +static int GetResidualCost_SSE2(int ctx0, const VP8Residual* const res) { uint8_t levels[16], ctxs[16]; uint16_t abs_levels[16]; int n = res->first; @@ -108,8 +108,8 @@ static int GetResidualCostSSE2(int ctx0, const VP8Residual* const res) { extern void VP8EncDspCostInitSSE2(void); WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspCostInitSSE2(void) { - VP8SetResidualCoeffs = SetResidualCoeffsSSE2; - VP8GetResidualCost = GetResidualCostSSE2; + VP8SetResidualCoeffs = SetResidualCoeffs_SSE2; + VP8GetResidualCost = GetResidualCost_SSE2; } #else // !WEBP_USE_SSE2 diff --git a/3rdparty/libwebp/dsp/cpu.c b/3rdparty/libwebp/src/dsp/cpu.c similarity index 98% rename from 3rdparty/libwebp/dsp/cpu.c rename to 3rdparty/libwebp/src/dsp/cpu.c index b5583b6e9b..8b40feed29 100644 --- a/3rdparty/libwebp/dsp/cpu.c +++ b/3rdparty/libwebp/src/dsp/cpu.c @@ -11,7 +11,7 @@ // // Author: Christian Duvivier (cduvivier@google.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_HAVE_NEON_RTCD) #include @@ -143,7 +143,7 @@ static int x86CPUInfo(CPUFeature feature) { return !!(cpu_info[2] & (1 << 0)); } if (feature == kSlowSSSE3) { - if (is_intel && (cpu_info[2] & (1 << 0))) { // SSSE3? + if (is_intel && (cpu_info[2] & (1 << 9))) { // SSSE3? return CheckSlowModel(cpu_info[0]); } return 0; diff --git a/3rdparty/libwebp/dsp/dec.c b/3rdparty/libwebp/src/dsp/dec.c similarity index 62% rename from 3rdparty/libwebp/dsp/dec.c rename to 3rdparty/libwebp/src/dsp/dec.c index 007e985d8b..7e82407567 100644 --- a/3rdparty/libwebp/dsp/dec.c +++ b/3rdparty/libwebp/src/dsp/dec.c @@ -11,9 +11,11 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" -#include "../dec/vp8i_dec.h" -#include "../utils/utils.h" +#include + +#include "src/dsp/dsp.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ @@ -25,7 +27,7 @@ static WEBP_INLINE uint8_t clip_8b(int v) { // Transforms (Paragraph 14.4) #define STORE(x, y, v) \ - dst[x + y * BPS] = clip_8b(dst[x + y * BPS] + ((v) >> 3)) + dst[(x) + (y) * BPS] = clip_8b(dst[(x) + (y) * BPS] + ((v) >> 3)) #define STORE2(y, dc, d, c) do { \ const int DC = (dc); \ @@ -38,7 +40,8 @@ static WEBP_INLINE uint8_t clip_8b(int v) { #define MUL1(a) ((((a) * 20091) >> 16) + (a)) #define MUL2(a) (((a) * 35468) >> 16) -static void TransformOne(const int16_t* in, uint8_t* dst) { +#if !WEBP_NEON_OMIT_C_CODE +static void TransformOne_C(const int16_t* in, uint8_t* dst) { int C[4 * 4], *tmp; int i; tmp = C; @@ -78,7 +81,7 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { } // Simplified transform when only in[0], in[1] and in[4] are non-zero -static void TransformAC3(const int16_t* in, uint8_t* dst) { +static void TransformAC3_C(const int16_t* in, uint8_t* dst) { const int a = in[0] + 4; const int c4 = MUL2(in[4]); const int d4 = MUL1(in[4]); @@ -93,19 +96,21 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) { #undef MUL2 #undef STORE2 -static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { - TransformOne(in, dst); +static void TransformTwo_C(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne_C(in, dst); if (do_two) { - TransformOne(in + 16, dst + 4); + TransformOne_C(in + 16, dst + 4); } } +#endif // !WEBP_NEON_OMIT_C_CODE -static void TransformUV(const int16_t* in, uint8_t* dst) { +static void TransformUV_C(const int16_t* in, uint8_t* dst) { VP8Transform(in + 0 * 16, dst, 1); VP8Transform(in + 2 * 16, dst + 4 * BPS, 1); } -static void TransformDC(const int16_t* in, uint8_t* dst) { +#if !WEBP_NEON_OMIT_C_CODE +static void TransformDC_C(const int16_t* in, uint8_t* dst) { const int DC = in[0] + 4; int i, j; for (j = 0; j < 4; ++j) { @@ -114,8 +119,9 @@ static void TransformDC(const int16_t* in, uint8_t* dst) { } } } +#endif // !WEBP_NEON_OMIT_C_CODE -static void TransformDCUV(const int16_t* in, uint8_t* dst) { +static void TransformDCUV_C(const int16_t* in, uint8_t* dst) { if (in[0 * 16]) VP8TransformDC(in + 0 * 16, dst); if (in[1 * 16]) VP8TransformDC(in + 1 * 16, dst + 4); if (in[2 * 16]) VP8TransformDC(in + 2 * 16, dst + 4 * BPS); @@ -127,7 +133,8 @@ static void TransformDCUV(const int16_t* in, uint8_t* dst) { //------------------------------------------------------------------------------ // Paragraph 14.3 -static void TransformWHT(const int16_t* in, int16_t* out) { +#if !WEBP_NEON_OMIT_C_CODE +static void TransformWHT_C(const int16_t* in, int16_t* out) { int tmp[16]; int i; for (i = 0; i < 4; ++i) { @@ -153,6 +160,7 @@ static void TransformWHT(const int16_t* in, int16_t* out) { out += 64; } } +#endif // !WEBP_NEON_OMIT_C_CODE void (*VP8TransformWHT)(const int16_t* in, int16_t* out); @@ -161,6 +169,7 @@ void (*VP8TransformWHT)(const int16_t* in, int16_t* out); #define DST(x, y) dst[(x) + (y) * BPS] +#if !WEBP_NEON_OMIT_C_CODE static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { const uint8_t* top = dst - BPS; const uint8_t* const clip0 = VP8kclip1 - top[-1]; @@ -174,21 +183,21 @@ static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { dst += BPS; } } -static void TM4(uint8_t* dst) { TrueMotion(dst, 4); } -static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); } -static void TM16(uint8_t* dst) { TrueMotion(dst, 16); } +static void TM4_C(uint8_t* dst) { TrueMotion(dst, 4); } +static void TM8uv_C(uint8_t* dst) { TrueMotion(dst, 8); } +static void TM16_C(uint8_t* dst) { TrueMotion(dst, 16); } //------------------------------------------------------------------------------ // 16x16 -static void VE16(uint8_t* dst) { // vertical +static void VE16_C(uint8_t* dst) { // vertical int j; for (j = 0; j < 16; ++j) { memcpy(dst + j * BPS, dst - BPS, 16); } } -static void HE16(uint8_t* dst) { // horizontal +static void HE16_C(uint8_t* dst) { // horizontal int j; for (j = 16; j > 0; --j) { memset(dst, dst[-1], 16); @@ -203,7 +212,7 @@ static WEBP_INLINE void Put16(int v, uint8_t* dst) { } } -static void DC16(uint8_t* dst) { // DC +static void DC16_C(uint8_t* dst) { // DC int DC = 16; int j; for (j = 0; j < 16; ++j) { @@ -212,7 +221,7 @@ static void DC16(uint8_t* dst) { // DC Put16(DC >> 5, dst); } -static void DC16NoTop(uint8_t* dst) { // DC with top samples not available +static void DC16NoTop_C(uint8_t* dst) { // DC with top samples not available int DC = 8; int j; for (j = 0; j < 16; ++j) { @@ -221,7 +230,7 @@ static void DC16NoTop(uint8_t* dst) { // DC with top samples not available Put16(DC >> 4, dst); } -static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available +static void DC16NoLeft_C(uint8_t* dst) { // DC with left samples not available int DC = 8; int i; for (i = 0; i < 16; ++i) { @@ -230,9 +239,10 @@ static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available Put16(DC >> 4, dst); } -static void DC16NoTopLeft(uint8_t* dst) { // DC with no top and left samples +static void DC16NoTopLeft_C(uint8_t* dst) { // DC with no top and left samples Put16(0x80, dst); } +#endif // !WEBP_NEON_OMIT_C_CODE VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES]; @@ -242,7 +252,8 @@ VP8PredFunc VP8PredLuma16[NUM_B_DC_MODES]; #define AVG3(a, b, c) ((uint8_t)(((a) + 2 * (b) + (c) + 2) >> 2)) #define AVG2(a, b) (((a) + (b) + 1) >> 1) -static void VE4(uint8_t* dst) { // vertical +#if !WEBP_NEON_OMIT_C_CODE +static void VE4_C(uint8_t* dst) { // vertical const uint8_t* top = dst - BPS; const uint8_t vals[4] = { AVG3(top[-1], top[0], top[1]), @@ -255,8 +266,9 @@ static void VE4(uint8_t* dst) { // vertical memcpy(dst + i * BPS, vals, sizeof(vals)); } } +#endif // !WEBP_NEON_OMIT_C_CODE -static void HE4(uint8_t* dst) { // horizontal +static void HE4_C(uint8_t* dst) { // horizontal const int A = dst[-1 - BPS]; const int B = dst[-1]; const int C = dst[-1 + BPS]; @@ -268,7 +280,8 @@ static void HE4(uint8_t* dst) { // horizontal WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(D, E, E)); } -static void DC4(uint8_t* dst) { // DC +#if !WEBP_NEON_OMIT_C_CODE +static void DC4_C(uint8_t* dst) { // DC uint32_t dc = 4; int i; for (i = 0; i < 4; ++i) dc += dst[i - BPS] + dst[-1 + i * BPS]; @@ -276,7 +289,7 @@ static void DC4(uint8_t* dst) { // DC for (i = 0; i < 4; ++i) memset(dst + i * BPS, dc, 4); } -static void RD4(uint8_t* dst) { // Down-right +static void RD4_C(uint8_t* dst) { // Down-right const int I = dst[-1 + 0 * BPS]; const int J = dst[-1 + 1 * BPS]; const int K = dst[-1 + 2 * BPS]; @@ -295,7 +308,7 @@ static void RD4(uint8_t* dst) { // Down-right DST(3, 0) = AVG3(D, C, B); } -static void LD4(uint8_t* dst) { // Down-Left +static void LD4_C(uint8_t* dst) { // Down-Left const int A = dst[0 - BPS]; const int B = dst[1 - BPS]; const int C = dst[2 - BPS]; @@ -312,8 +325,9 @@ static void LD4(uint8_t* dst) { // Down-Left DST(3, 2) = DST(2, 3) = AVG3(F, G, H); DST(3, 3) = AVG3(G, H, H); } +#endif // !WEBP_NEON_OMIT_C_CODE -static void VR4(uint8_t* dst) { // Vertical-Right +static void VR4_C(uint8_t* dst) { // Vertical-Right const int I = dst[-1 + 0 * BPS]; const int J = dst[-1 + 1 * BPS]; const int K = dst[-1 + 2 * BPS]; @@ -335,7 +349,7 @@ static void VR4(uint8_t* dst) { // Vertical-Right DST(3, 1) = AVG3(B, C, D); } -static void VL4(uint8_t* dst) { // Vertical-Left +static void VL4_C(uint8_t* dst) { // Vertical-Left const int A = dst[0 - BPS]; const int B = dst[1 - BPS]; const int C = dst[2 - BPS]; @@ -357,7 +371,7 @@ static void VL4(uint8_t* dst) { // Vertical-Left DST(3, 3) = AVG3(F, G, H); } -static void HU4(uint8_t* dst) { // Horizontal-Up +static void HU4_C(uint8_t* dst) { // Horizontal-Up const int I = dst[-1 + 0 * BPS]; const int J = dst[-1 + 1 * BPS]; const int K = dst[-1 + 2 * BPS]; @@ -372,7 +386,7 @@ static void HU4(uint8_t* dst) { // Horizontal-Up DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; } -static void HD4(uint8_t* dst) { // Horizontal-Down +static void HD4_C(uint8_t* dst) { // Horizontal-Down const int I = dst[-1 + 0 * BPS]; const int J = dst[-1 + 1 * BPS]; const int K = dst[-1 + 2 * BPS]; @@ -404,14 +418,15 @@ VP8PredFunc VP8PredLuma4[NUM_BMODES]; //------------------------------------------------------------------------------ // Chroma -static void VE8uv(uint8_t* dst) { // vertical +#if !WEBP_NEON_OMIT_C_CODE +static void VE8uv_C(uint8_t* dst) { // vertical int j; for (j = 0; j < 8; ++j) { memcpy(dst + j * BPS, dst - BPS, 8); } } -static void HE8uv(uint8_t* dst) { // horizontal +static void HE8uv_C(uint8_t* dst) { // horizontal int j; for (j = 0; j < 8; ++j) { memset(dst, dst[-1], 8); @@ -427,7 +442,7 @@ static WEBP_INLINE void Put8x8uv(uint8_t value, uint8_t* dst) { } } -static void DC8uv(uint8_t* dst) { // DC +static void DC8uv_C(uint8_t* dst) { // DC int dc0 = 8; int i; for (i = 0; i < 8; ++i) { @@ -436,7 +451,7 @@ static void DC8uv(uint8_t* dst) { // DC Put8x8uv(dc0 >> 4, dst); } -static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples +static void DC8uvNoLeft_C(uint8_t* dst) { // DC with no left samples int dc0 = 4; int i; for (i = 0; i < 8; ++i) { @@ -445,7 +460,7 @@ static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples Put8x8uv(dc0 >> 3, dst); } -static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples +static void DC8uvNoTop_C(uint8_t* dst) { // DC with no top samples int dc0 = 4; int i; for (i = 0; i < 8; ++i) { @@ -454,17 +469,19 @@ static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples Put8x8uv(dc0 >> 3, dst); } -static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing +static void DC8uvNoTopLeft_C(uint8_t* dst) { // DC with nothing Put8x8uv(0x80, dst); } +#endif // !WEBP_NEON_OMIT_C_CODE VP8PredFunc VP8PredChroma8[NUM_B_DC_MODES]; //------------------------------------------------------------------------------ // Edge filtering functions +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC // 4 pixels in, 2 pixels out -static WEBP_INLINE void do_filter2(uint8_t* p, int step) { +static WEBP_INLINE void DoFilter2_C(uint8_t* p, int step) { const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; const int a = 3 * (q0 - p0) + VP8ksclip1[p1 - q1]; // in [-893,892] const int a1 = VP8ksclip2[(a + 4) >> 3]; // in [-16,15] @@ -474,7 +491,7 @@ static WEBP_INLINE void do_filter2(uint8_t* p, int step) { } // 4 pixels in, 4 pixels out -static WEBP_INLINE void do_filter4(uint8_t* p, int step) { +static WEBP_INLINE void DoFilter4_C(uint8_t* p, int step) { const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; const int a = 3 * (q0 - p0); const int a1 = VP8ksclip2[(a + 4) >> 3]; @@ -487,7 +504,7 @@ static WEBP_INLINE void do_filter4(uint8_t* p, int step) { } // 6 pixels in, 6 pixels out -static WEBP_INLINE void do_filter6(uint8_t* p, int step) { +static WEBP_INLINE void DoFilter6_C(uint8_t* p, int step) { const int p2 = p[-3*step], p1 = p[-2*step], p0 = p[-step]; const int q0 = p[0], q1 = p[step], q2 = p[2*step]; const int a = VP8ksclip1[3 * (q0 - p0) + VP8ksclip1[p1 - q1]]; @@ -503,18 +520,22 @@ static WEBP_INLINE void do_filter6(uint8_t* p, int step) { p[ 2*step] = VP8kclip1[q2 - a3]; } -static WEBP_INLINE int hev(const uint8_t* p, int step, int thresh) { +static WEBP_INLINE int Hev(const uint8_t* p, int step, int thresh) { const int p1 = p[-2*step], p0 = p[-step], q0 = p[0], q1 = p[step]; return (VP8kabs0[p1 - p0] > thresh) || (VP8kabs0[q1 - q0] > thresh); } +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC -static WEBP_INLINE int needs_filter(const uint8_t* p, int step, int t) { +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE int NeedsFilter_C(const uint8_t* p, int step, int t) { const int p1 = p[-2 * step], p0 = p[-step], q0 = p[0], q1 = p[step]; return ((4 * VP8kabs0[p0 - q0] + VP8kabs0[p1 - q1]) <= t); } +#endif // !WEBP_NEON_OMIT_C_CODE -static WEBP_INLINE int needs_filter2(const uint8_t* p, - int step, int t, int it) { +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static WEBP_INLINE int NeedsFilter2_C(const uint8_t* p, + int step, int t, int it) { const int p3 = p[-4 * step], p2 = p[-3 * step], p1 = p[-2 * step]; const int p0 = p[-step], q0 = p[0]; const int q1 = p[step], q2 = p[2 * step], q3 = p[3 * step]; @@ -523,140 +544,159 @@ static WEBP_INLINE int needs_filter2(const uint8_t* p, VP8kabs0[p1 - p0] <= it && VP8kabs0[q3 - q2] <= it && VP8kabs0[q2 - q1] <= it && VP8kabs0[q1 - q0] <= it; } +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC //------------------------------------------------------------------------------ // Simple In-loop filtering (Paragraph 15.2) -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { +#if !WEBP_NEON_OMIT_C_CODE +static void SimpleVFilter16_C(uint8_t* p, int stride, int thresh) { int i; const int thresh2 = 2 * thresh + 1; for (i = 0; i < 16; ++i) { - if (needs_filter(p + i, stride, thresh2)) { - do_filter2(p + i, stride); + if (NeedsFilter_C(p + i, stride, thresh2)) { + DoFilter2_C(p + i, stride); } } } -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { +static void SimpleHFilter16_C(uint8_t* p, int stride, int thresh) { int i; const int thresh2 = 2 * thresh + 1; for (i = 0; i < 16; ++i) { - if (needs_filter(p + i * stride, 1, thresh2)) { - do_filter2(p + i * stride, 1); + if (NeedsFilter_C(p + i * stride, 1, thresh2)) { + DoFilter2_C(p + i * stride, 1); } } } -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { +static void SimpleVFilter16i_C(uint8_t* p, int stride, int thresh) { int k; for (k = 3; k > 0; --k) { p += 4 * stride; - SimpleVFilter16(p, stride, thresh); + SimpleVFilter16_C(p, stride, thresh); } } -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { +static void SimpleHFilter16i_C(uint8_t* p, int stride, int thresh) { int k; for (k = 3; k > 0; --k) { p += 4; - SimpleHFilter16(p, stride, thresh); + SimpleHFilter16_C(p, stride, thresh); } } +#endif // !WEBP_NEON_OMIT_C_CODE //------------------------------------------------------------------------------ // Complex In-loop filtering (Paragraph 15.3) -static WEBP_INLINE void FilterLoop26(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static WEBP_INLINE void FilterLoop26_C(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, + int hev_thresh) { const int thresh2 = 2 * thresh + 1; while (size-- > 0) { - if (needs_filter2(p, hstride, thresh2, ithresh)) { - if (hev(p, hstride, hev_thresh)) { - do_filter2(p, hstride); + if (NeedsFilter2_C(p, hstride, thresh2, ithresh)) { + if (Hev(p, hstride, hev_thresh)) { + DoFilter2_C(p, hstride); } else { - do_filter6(p, hstride); + DoFilter6_C(p, hstride); } } p += vstride; } } -static WEBP_INLINE void FilterLoop24(uint8_t* p, - int hstride, int vstride, int size, - int thresh, int ithresh, int hev_thresh) { +static WEBP_INLINE void FilterLoop24_C(uint8_t* p, + int hstride, int vstride, int size, + int thresh, int ithresh, + int hev_thresh) { const int thresh2 = 2 * thresh + 1; while (size-- > 0) { - if (needs_filter2(p, hstride, thresh2, ithresh)) { - if (hev(p, hstride, hev_thresh)) { - do_filter2(p, hstride); + if (NeedsFilter2_C(p, hstride, thresh2, ithresh)) { + if (Hev(p, hstride, hev_thresh)) { + DoFilter2_C(p, hstride); } else { - do_filter4(p, hstride); + DoFilter4_C(p, hstride); } } p += vstride; } } +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +#if !WEBP_NEON_OMIT_C_CODE // on macroblock edges -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, stride, 1, 16, thresh, ithresh, hev_thresh); +static void VFilter16_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(p, stride, 1, 16, thresh, ithresh, hev_thresh); } -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(p, 1, stride, 16, thresh, ithresh, hev_thresh); +static void HFilter16_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(p, 1, stride, 16, thresh, ithresh, hev_thresh); } // on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { +static void VFilter16i_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { int k; for (k = 3; k > 0; --k) { p += 4 * stride; - FilterLoop24(p, stride, 1, 16, thresh, ithresh, hev_thresh); + FilterLoop24_C(p, stride, 1, 16, thresh, ithresh, hev_thresh); } } +#endif // !WEBP_NEON_OMIT_C_CODE -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static void HFilter16i_C(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { int k; for (k = 3; k > 0; --k) { p += 4; - FilterLoop24(p, 1, stride, 16, thresh, ithresh, hev_thresh); + FilterLoop24_C(p, 1, stride, 16, thresh, ithresh, hev_thresh); } } +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +#if !WEBP_NEON_OMIT_C_CODE // 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, stride, 1, 8, thresh, ithresh, hev_thresh); +static void VFilter8_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(u, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop26_C(v, stride, 1, 8, thresh, ithresh, hev_thresh); } +#endif // !WEBP_NEON_OMIT_C_CODE -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop26(u, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop26(v, 1, stride, 8, thresh, ithresh, hev_thresh); +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static void HFilter8_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop26_C(u, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop26_C(v, 1, stride, 8, thresh, ithresh, hev_thresh); } +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); +#if !WEBP_NEON_OMIT_C_CODE +static void VFilter8i_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24_C(u + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); + FilterLoop24_C(v + 4 * stride, stride, 1, 8, thresh, ithresh, hev_thresh); } +#endif // !WEBP_NEON_OMIT_C_CODE -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { - FilterLoop24(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); - FilterLoop24(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static void HFilter8i_C(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { + FilterLoop24_C(u + 4, 1, stride, 8, thresh, ithresh, hev_thresh); + FilterLoop24_C(v + 4, 1, stride, 8, thresh, ithresh, hev_thresh); } +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC //------------------------------------------------------------------------------ -static void DitherCombine8x8(const uint8_t* dither, uint8_t* dst, - int dst_stride) { +static void DitherCombine8x8_C(const uint8_t* dither, uint8_t* dst, + int dst_stride) { int i, j; for (j = 0; j < 8; ++j) { for (i = 0; i < 8; ++i) { @@ -709,54 +749,66 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) { VP8InitClipTables(); - VP8TransformWHT = TransformWHT; - VP8Transform = TransformTwo; - VP8TransformUV = TransformUV; - VP8TransformDC = TransformDC; - VP8TransformDCUV = TransformDCUV; - VP8TransformAC3 = TransformAC3; +#if !WEBP_NEON_OMIT_C_CODE + VP8TransformWHT = TransformWHT_C; + VP8Transform = TransformTwo_C; + VP8TransformDC = TransformDC_C; + VP8TransformAC3 = TransformAC3_C; +#endif + VP8TransformUV = TransformUV_C; + VP8TransformDCUV = TransformDCUV_C; - VP8VFilter16 = VFilter16; - VP8HFilter16 = HFilter16; - VP8VFilter8 = VFilter8; - VP8HFilter8 = HFilter8; - VP8VFilter16i = VFilter16i; - VP8HFilter16i = HFilter16i; - VP8VFilter8i = VFilter8i; - VP8HFilter8i = HFilter8i; - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; +#if !WEBP_NEON_OMIT_C_CODE + VP8VFilter16 = VFilter16_C; + VP8VFilter16i = VFilter16i_C; + VP8HFilter16 = HFilter16_C; + VP8VFilter8 = VFilter8_C; + VP8VFilter8i = VFilter8i_C; + VP8SimpleVFilter16 = SimpleVFilter16_C; + VP8SimpleHFilter16 = SimpleHFilter16_C; + VP8SimpleVFilter16i = SimpleVFilter16i_C; + VP8SimpleHFilter16i = SimpleHFilter16i_C; +#endif - VP8PredLuma4[0] = DC4; - VP8PredLuma4[1] = TM4; - VP8PredLuma4[2] = VE4; - VP8PredLuma4[3] = HE4; - VP8PredLuma4[4] = RD4; - VP8PredLuma4[5] = VR4; - VP8PredLuma4[6] = LD4; - VP8PredLuma4[7] = VL4; - VP8PredLuma4[8] = HD4; - VP8PredLuma4[9] = HU4; +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + VP8HFilter16i = HFilter16i_C; + VP8HFilter8 = HFilter8_C; + VP8HFilter8i = HFilter8i_C; +#endif - VP8PredLuma16[0] = DC16; - VP8PredLuma16[1] = TM16; - VP8PredLuma16[2] = VE16; - VP8PredLuma16[3] = HE16; - VP8PredLuma16[4] = DC16NoTop; - VP8PredLuma16[5] = DC16NoLeft; - VP8PredLuma16[6] = DC16NoTopLeft; +#if !WEBP_NEON_OMIT_C_CODE + VP8PredLuma4[0] = DC4_C; + VP8PredLuma4[1] = TM4_C; + VP8PredLuma4[2] = VE4_C; + VP8PredLuma4[4] = RD4_C; + VP8PredLuma4[6] = LD4_C; +#endif - VP8PredChroma8[0] = DC8uv; - VP8PredChroma8[1] = TM8uv; - VP8PredChroma8[2] = VE8uv; - VP8PredChroma8[3] = HE8uv; - VP8PredChroma8[4] = DC8uvNoTop; - VP8PredChroma8[5] = DC8uvNoLeft; - VP8PredChroma8[6] = DC8uvNoTopLeft; + VP8PredLuma4[3] = HE4_C; + VP8PredLuma4[5] = VR4_C; + VP8PredLuma4[7] = VL4_C; + VP8PredLuma4[8] = HD4_C; + VP8PredLuma4[9] = HU4_C; - VP8DitherCombine8x8 = DitherCombine8x8; +#if !WEBP_NEON_OMIT_C_CODE + VP8PredLuma16[0] = DC16_C; + VP8PredLuma16[1] = TM16_C; + VP8PredLuma16[2] = VE16_C; + VP8PredLuma16[3] = HE16_C; + VP8PredLuma16[4] = DC16NoTop_C; + VP8PredLuma16[5] = DC16NoLeft_C; + VP8PredLuma16[6] = DC16NoTopLeft_C; + + VP8PredChroma8[0] = DC8uv_C; + VP8PredChroma8[1] = TM8uv_C; + VP8PredChroma8[2] = VE8uv_C; + VP8PredChroma8[3] = HE8uv_C; + VP8PredChroma8[4] = DC8uvNoTop_C; + VP8PredChroma8[5] = DC8uvNoLeft_C; + VP8PredChroma8[6] = DC8uvNoTopLeft_C; +#endif + + VP8DitherCombine8x8 = DitherCombine8x8_C; // If defined, use CPUInfo() to overwrite some pointers with faster versions. if (VP8GetCPUInfo != NULL) { @@ -770,11 +822,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) { #endif } #endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8DspInitNEON(); - } -#endif #if defined(WEBP_USE_MIPS32) if (VP8GetCPUInfo(kMIPS32)) { VP8DspInitMIPS32(); @@ -791,5 +838,57 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8DspInit(void) { } #endif } + +#if defined(WEBP_USE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8DspInitNEON(); + } +#endif + + assert(VP8TransformWHT != NULL); + assert(VP8Transform != NULL); + assert(VP8TransformDC != NULL); + assert(VP8TransformAC3 != NULL); + assert(VP8TransformUV != NULL); + assert(VP8TransformDCUV != NULL); + assert(VP8VFilter16 != NULL); + assert(VP8HFilter16 != NULL); + assert(VP8VFilter8 != NULL); + assert(VP8HFilter8 != NULL); + assert(VP8VFilter16i != NULL); + assert(VP8HFilter16i != NULL); + assert(VP8VFilter8i != NULL); + assert(VP8HFilter8i != NULL); + assert(VP8SimpleVFilter16 != NULL); + assert(VP8SimpleHFilter16 != NULL); + assert(VP8SimpleVFilter16i != NULL); + assert(VP8SimpleHFilter16i != NULL); + assert(VP8PredLuma4[0] != NULL); + assert(VP8PredLuma4[1] != NULL); + assert(VP8PredLuma4[2] != NULL); + assert(VP8PredLuma4[3] != NULL); + assert(VP8PredLuma4[4] != NULL); + assert(VP8PredLuma4[5] != NULL); + assert(VP8PredLuma4[6] != NULL); + assert(VP8PredLuma4[7] != NULL); + assert(VP8PredLuma4[8] != NULL); + assert(VP8PredLuma4[9] != NULL); + assert(VP8PredLuma16[0] != NULL); + assert(VP8PredLuma16[1] != NULL); + assert(VP8PredLuma16[2] != NULL); + assert(VP8PredLuma16[3] != NULL); + assert(VP8PredLuma16[4] != NULL); + assert(VP8PredLuma16[5] != NULL); + assert(VP8PredLuma16[6] != NULL); + assert(VP8PredChroma8[0] != NULL); + assert(VP8PredChroma8[1] != NULL); + assert(VP8PredChroma8[2] != NULL); + assert(VP8PredChroma8[3] != NULL); + assert(VP8PredChroma8[4] != NULL); + assert(VP8PredChroma8[5] != NULL); + assert(VP8PredChroma8[6] != NULL); + assert(VP8DitherCombine8x8 != NULL); + dec_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/3rdparty/libwebp/dsp/dec_clip_tables.c b/3rdparty/libwebp/src/dsp/dec_clip_tables.c similarity index 99% rename from 3rdparty/libwebp/dsp/dec_clip_tables.c rename to 3rdparty/libwebp/src/dsp/dec_clip_tables.c index 74ba34c0bb..427b74f776 100644 --- a/3rdparty/libwebp/dsp/dec_clip_tables.c +++ b/3rdparty/libwebp/src/dsp/dec_clip_tables.c @@ -11,11 +11,14 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" -#define USE_STATIC_TABLES // undefine to have run-time table initialization +// define to 0 to have run-time table initialization +#if !defined(USE_STATIC_TABLES) +#define USE_STATIC_TABLES 1 // ALTERNATE_CODE +#endif -#ifdef USE_STATIC_TABLES +#if (USE_STATIC_TABLES == 1) static const uint8_t abs0[255 + 255 + 1] = { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, @@ -337,7 +340,7 @@ static uint8_t clip1[255 + 511 + 1]; // and make sure it's set to true _last_ (so as to be thread-safe) static volatile int tables_ok = 0; -#endif +#endif // USE_STATIC_TABLES const int8_t* const VP8ksclip1 = (const int8_t*)&sclip1[1020]; const int8_t* const VP8ksclip2 = (const int8_t*)&sclip2[112]; @@ -345,7 +348,7 @@ const uint8_t* const VP8kclip1 = &clip1[255]; const uint8_t* const VP8kabs0 = &abs0[255]; WEBP_TSAN_IGNORE_FUNCTION void VP8InitClipTables(void) { -#if !defined(USE_STATIC_TABLES) +#if (USE_STATIC_TABLES == 0) int i; if (!tables_ok) { for (i = -255; i <= 255; ++i) { diff --git a/3rdparty/libwebp/dsp/dec_mips32.c b/3rdparty/libwebp/src/dsp/dec_mips32.c similarity index 99% rename from 3rdparty/libwebp/dsp/dec_mips32.c rename to 3rdparty/libwebp/src/dsp/dec_mips32.c index 4e9ef42605..e4e70966d2 100644 --- a/3rdparty/libwebp/dsp/dec_mips32.c +++ b/3rdparty/libwebp/src/dsp/dec_mips32.c @@ -12,11 +12,11 @@ // Author(s): Djordje Pesut (djordje.pesut@imgtec.com) // Jovan Zelincevic (jovan.zelincevic@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS32) -#include "./mips_macro.h" +#include "src/dsp/mips_macro.h" static const int kC1 = 20091 + (1 << 16); static const int kC2 = 35468; diff --git a/3rdparty/libwebp/dsp/dec_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/dec_mips_dsp_r2.c similarity index 99% rename from 3rdparty/libwebp/dsp/dec_mips_dsp_r2.c rename to 3rdparty/libwebp/src/dsp/dec_mips_dsp_r2.c index db5c657228..b0936bc46e 100644 --- a/3rdparty/libwebp/dsp/dec_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/dec_mips_dsp_r2.c @@ -12,11 +12,11 @@ // Author(s): Djordje Pesut (djordje.pesut@imgtec.com) // Jovan Zelincevic (jovan.zelincevic@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS_DSP_R2) -#include "./mips_macro.h" +#include "src/dsp/mips_macro.h" static const int kC1 = 20091 + (1 << 16); static const int kC2 = 35468; diff --git a/3rdparty/libwebp/dsp/dec_msa.c b/3rdparty/libwebp/src/dsp/dec_msa.c similarity index 99% rename from 3rdparty/libwebp/dsp/dec_msa.c rename to 3rdparty/libwebp/src/dsp/dec_msa.c index 8d9c98c3cf..8090622b7b 100644 --- a/3rdparty/libwebp/dsp/dec_msa.c +++ b/3rdparty/libwebp/src/dsp/dec_msa.c @@ -12,11 +12,11 @@ // Author(s): Prashant Patil (prashant.patil@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MSA) -#include "./msa_macro.h" +#include "src/dsp/msa_macro.h" //------------------------------------------------------------------------------ // Transforms @@ -222,6 +222,7 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) { const v16i8 cnst4b = __msa_ldi_b(4); \ const v16i8 cnst3b = __msa_ldi_b(3); \ const v8i16 cnst9h = __msa_ldi_h(9); \ + const v8i16 cnst63h = __msa_ldi_h(63); \ \ FLIP_SIGN4(p1, p0, q0, q1, p1_m, p0_m, q0_m, q1_m); \ filt = __msa_subs_s_b(p1_m, q1_m); \ @@ -241,9 +242,9 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) { ILVRL_B2_SH(filt_sign, filt, filt_r, filt_l); \ /* update q2/p2 */ \ temp0 = filt_r * cnst9h; \ - temp1 = ADDVI_H(temp0, 63); \ + temp1 = temp0 + cnst63h; \ temp2 = filt_l * cnst9h; \ - temp3 = ADDVI_H(temp2, 63); \ + temp3 = temp2 + cnst63h; \ FILT2(q2_m, p2_m, q2, p2); \ /* update q1/p1 */ \ temp1 = temp1 + temp0; \ @@ -708,7 +709,7 @@ static void VE4(uint8_t* dst) { // vertical const uint32_t val0 = LW(ptop + 0); const uint32_t val1 = LW(ptop + 4); uint32_t out; - v16u8 A, B, C, AC, B2, R; + v16u8 A = { 0 }, B, C, AC, B2, R; INSERT_W2_UB(val0, val1, A); B = SLDI_UB(A, A, 1); @@ -725,7 +726,7 @@ static void RD4(uint8_t* dst) { // Down-right uint32_t val0 = LW(ptop + 0); uint32_t val1 = LW(ptop + 4); uint32_t val2, val3; - v16u8 A, B, C, AC, B2, R, A1; + v16u8 A, B, C, AC, B2, R, A1 = { 0 }; INSERT_W2_UB(val0, val1, A1); A = SLDI_UB(A1, A1, 12); @@ -753,7 +754,7 @@ static void LD4(uint8_t* dst) { // Down-Left uint32_t val0 = LW(ptop + 0); uint32_t val1 = LW(ptop + 4); uint32_t val2, val3; - v16u8 A, B, C, AC, B2, R; + v16u8 A = { 0 }, B, C, AC, B2, R; INSERT_W2_UB(val0, val1, A); B = SLDI_UB(A, A, 1); diff --git a/3rdparty/libwebp/dsp/dec_neon.c b/3rdparty/libwebp/src/dsp/dec_neon.c similarity index 71% rename from 3rdparty/libwebp/dsp/dec_neon.c rename to 3rdparty/libwebp/src/dsp/dec_neon.c index 34796cf4a2..ffa697fcf9 100644 --- a/3rdparty/libwebp/dsp/dec_neon.c +++ b/3rdparty/libwebp/src/dsp/dec_neon.c @@ -12,43 +12,23 @@ // Authors: Somnath Banerjee (somnath@google.com) // Johann Koenig (johannkoenig@google.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_NEON) -#include "./neon.h" -#include "../dec/vp8i_dec.h" +#include "src/dsp/neon.h" +#include "src/dec/vp8i_dec.h" //------------------------------------------------------------------------------ // NxM Loading functions -// Load/Store vertical edge -#define LOAD8x4(c1, c2, c3, c4, b1, b2, stride) \ - "vld4.8 {" #c1 "[0]," #c2 "[0]," #c3 "[0]," #c4 "[0]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[1]," #c2 "[1]," #c3 "[1]," #c4 "[1]}," #b2 "," #stride "\n" \ - "vld4.8 {" #c1 "[2]," #c2 "[2]," #c3 "[2]," #c4 "[2]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[3]," #c2 "[3]," #c3 "[3]," #c4 "[3]}," #b2 "," #stride "\n" \ - "vld4.8 {" #c1 "[4]," #c2 "[4]," #c3 "[4]," #c4 "[4]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[5]," #c2 "[5]," #c3 "[5]," #c4 "[5]}," #b2 "," #stride "\n" \ - "vld4.8 {" #c1 "[6]," #c2 "[6]," #c3 "[6]," #c4 "[6]}," #b1 "," #stride "\n" \ - "vld4.8 {" #c1 "[7]," #c2 "[7]," #c3 "[7]," #c4 "[7]}," #b2 "," #stride "\n" - -#define STORE8x2(c1, c2, p, stride) \ - "vst2.8 {" #c1 "[0], " #c2 "[0]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[1], " #c2 "[1]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[2], " #c2 "[2]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[3], " #c2 "[3]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[4], " #c2 "[4]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[5], " #c2 "[5]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[6], " #c2 "[6]}," #p "," #stride " \n" \ - "vst2.8 {" #c1 "[7], " #c2 "[7]}," #p "," #stride " \n" - #if !defined(WORK_AROUND_GCC) // This intrinsics version makes gcc-4.6.3 crash during Load4x??() compilation // (register alloc, probably). The variants somewhat mitigate the problem, but // not quite. HFilter16i() remains problematic. -static WEBP_INLINE uint8x8x4_t Load4x8(const uint8_t* const src, int stride) { +static WEBP_INLINE uint8x8x4_t Load4x8_NEON(const uint8_t* const src, + int stride) { const uint8x8_t zero = vdup_n_u8(0); uint8x8x4_t out; INIT_VECTOR4(out, zero, zero, zero, zero); @@ -63,13 +43,15 @@ static WEBP_INLINE uint8x8x4_t Load4x8(const uint8_t* const src, int stride) { return out; } -static WEBP_INLINE void Load4x16(const uint8_t* const src, int stride, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1) { +static WEBP_INLINE void Load4x16_NEON(const uint8_t* const src, int stride, + uint8x16_t* const p1, + uint8x16_t* const p0, + uint8x16_t* const q0, + uint8x16_t* const q1) { // row0 = p1[0..7]|p0[0..7]|q0[0..7]|q1[0..7] // row8 = p1[8..15]|p0[8..15]|q0[8..15]|q1[8..15] - const uint8x8x4_t row0 = Load4x8(src - 2 + 0 * stride, stride); - const uint8x8x4_t row8 = Load4x8(src - 2 + 8 * stride, stride); + const uint8x8x4_t row0 = Load4x8_NEON(src - 2 + 0 * stride, stride); + const uint8x8x4_t row8 = Load4x8_NEON(src - 2 + 8 * stride, stride); *p1 = vcombine_u8(row0.val[0], row8.val[0]); *p0 = vcombine_u8(row0.val[1], row8.val[1]); *q0 = vcombine_u8(row0.val[2], row8.val[2]); @@ -83,9 +65,11 @@ static WEBP_INLINE void Load4x16(const uint8_t* const src, int stride, src += stride; \ } while (0) -static WEBP_INLINE void Load4x16(const uint8_t* src, int stride, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1) { +static WEBP_INLINE void Load4x16_NEON(const uint8_t* src, int stride, + uint8x16_t* const p1, + uint8x16_t* const p0, + uint8x16_t* const q0, + uint8x16_t* const q1) { const uint32x4_t zero = vdupq_n_u32(0); uint32x4x4_t in; INIT_VECTOR4(in, zero, zero, zero, zero); @@ -126,40 +110,40 @@ static WEBP_INLINE void Load4x16(const uint8_t* src, int stride, #endif // !WORK_AROUND_GCC -static WEBP_INLINE void Load8x16(const uint8_t* const src, int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { - Load4x16(src - 2, stride, p3, p2, p1, p0); - Load4x16(src + 2, stride, q0, q1, q2, q3); +static WEBP_INLINE void Load8x16_NEON( + const uint8_t* const src, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { + Load4x16_NEON(src - 2, stride, p3, p2, p1, p0); + Load4x16_NEON(src + 2, stride, q0, q1, q2, q3); } -static WEBP_INLINE void Load16x4(const uint8_t* const src, int stride, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1) { +static WEBP_INLINE void Load16x4_NEON(const uint8_t* const src, int stride, + uint8x16_t* const p1, + uint8x16_t* const p0, + uint8x16_t* const q0, + uint8x16_t* const q1) { *p1 = vld1q_u8(src - 2 * stride); *p0 = vld1q_u8(src - 1 * stride); *q0 = vld1q_u8(src + 0 * stride); *q1 = vld1q_u8(src + 1 * stride); } -static WEBP_INLINE void Load16x8(const uint8_t* const src, int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { - Load16x4(src - 2 * stride, stride, p3, p2, p1, p0); - Load16x4(src + 2 * stride, stride, q0, q1, q2, q3); +static WEBP_INLINE void Load16x8_NEON( + const uint8_t* const src, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { + Load16x4_NEON(src - 2 * stride, stride, p3, p2, p1, p0); + Load16x4_NEON(src + 2 * stride, stride, q0, q1, q2, q3); } -static WEBP_INLINE void Load8x8x2(const uint8_t* const u, - const uint8_t* const v, - int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { +static WEBP_INLINE void Load8x8x2_NEON( + const uint8_t* const u, const uint8_t* const v, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination // and the v-samples on the higher half. *p3 = vcombine_u8(vld1_u8(u - 4 * stride), vld1_u8(v - 4 * stride)); @@ -177,13 +161,11 @@ static WEBP_INLINE void Load8x8x2(const uint8_t* const u, #define LOAD_UV_8(ROW) \ vcombine_u8(vld1_u8(u - 4 + (ROW) * stride), vld1_u8(v - 4 + (ROW) * stride)) -static WEBP_INLINE void Load8x8x2T(const uint8_t* const u, - const uint8_t* const v, - int stride, - uint8x16_t* const p3, uint8x16_t* const p2, - uint8x16_t* const p1, uint8x16_t* const p0, - uint8x16_t* const q0, uint8x16_t* const q1, - uint8x16_t* const q2, uint8x16_t* const q3) { +static WEBP_INLINE void Load8x8x2T_NEON( + const uint8_t* const u, const uint8_t* const v, int stride, + uint8x16_t* const p3, uint8x16_t* const p2, uint8x16_t* const p1, + uint8x16_t* const p0, uint8x16_t* const q0, uint8x16_t* const q1, + uint8x16_t* const q2, uint8x16_t* const q3) { // We pack the 8x8 u-samples in the lower half of the uint8x16_t destination // and the v-samples on the higher half. const uint8x16_t row0 = LOAD_UV_8(0); @@ -238,8 +220,8 @@ static WEBP_INLINE void Load8x8x2T(const uint8_t* const u, #endif // !WORK_AROUND_GCC -static WEBP_INLINE void Store2x8(const uint8x8x2_t v, - uint8_t* const dst, int stride) { +static WEBP_INLINE void Store2x8_NEON(const uint8x8x2_t v, + uint8_t* const dst, int stride) { vst2_lane_u8(dst + 0 * stride, v, 0); vst2_lane_u8(dst + 1 * stride, v, 1); vst2_lane_u8(dst + 2 * stride, v, 2); @@ -250,20 +232,20 @@ static WEBP_INLINE void Store2x8(const uint8x8x2_t v, vst2_lane_u8(dst + 7 * stride, v, 7); } -static WEBP_INLINE void Store2x16(const uint8x16_t p0, const uint8x16_t q0, - uint8_t* const dst, int stride) { +static WEBP_INLINE void Store2x16_NEON(const uint8x16_t p0, const uint8x16_t q0, + uint8_t* const dst, int stride) { uint8x8x2_t lo, hi; lo.val[0] = vget_low_u8(p0); lo.val[1] = vget_low_u8(q0); hi.val[0] = vget_high_u8(p0); hi.val[1] = vget_high_u8(q0); - Store2x8(lo, dst - 1 + 0 * stride, stride); - Store2x8(hi, dst - 1 + 8 * stride, stride); + Store2x8_NEON(lo, dst - 1 + 0 * stride, stride); + Store2x8_NEON(hi, dst - 1 + 8 * stride, stride); } #if !defined(WORK_AROUND_GCC) -static WEBP_INLINE void Store4x8(const uint8x8x4_t v, - uint8_t* const dst, int stride) { +static WEBP_INLINE void Store4x8_NEON(const uint8x8x4_t v, + uint8_t* const dst, int stride) { vst4_lane_u8(dst + 0 * stride, v, 0); vst4_lane_u8(dst + 1 * stride, v, 1); vst4_lane_u8(dst + 2 * stride, v, 2); @@ -274,9 +256,9 @@ static WEBP_INLINE void Store4x8(const uint8x8x4_t v, vst4_lane_u8(dst + 7 * stride, v, 7); } -static WEBP_INLINE void Store4x16(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const dst, int stride) { +static WEBP_INLINE void Store4x16_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + uint8_t* const dst, int stride) { uint8x8x4_t lo, hi; INIT_VECTOR4(lo, vget_low_u8(p1), vget_low_u8(p0), @@ -284,27 +266,28 @@ static WEBP_INLINE void Store4x16(const uint8x16_t p1, const uint8x16_t p0, INIT_VECTOR4(hi, vget_high_u8(p1), vget_high_u8(p0), vget_high_u8(q0), vget_high_u8(q1)); - Store4x8(lo, dst - 2 + 0 * stride, stride); - Store4x8(hi, dst - 2 + 8 * stride, stride); + Store4x8_NEON(lo, dst - 2 + 0 * stride, stride); + Store4x8_NEON(hi, dst - 2 + 8 * stride, stride); } #endif // !WORK_AROUND_GCC -static WEBP_INLINE void Store16x2(const uint8x16_t p0, const uint8x16_t q0, - uint8_t* const dst, int stride) { +static WEBP_INLINE void Store16x2_NEON(const uint8x16_t p0, const uint8x16_t q0, + uint8_t* const dst, int stride) { vst1q_u8(dst - stride, p0); vst1q_u8(dst, q0); } -static WEBP_INLINE void Store16x4(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const dst, int stride) { - Store16x2(p1, p0, dst - stride, stride); - Store16x2(q0, q1, dst + stride, stride); +static WEBP_INLINE void Store16x4_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + uint8_t* const dst, int stride) { + Store16x2_NEON(p1, p0, dst - stride, stride); + Store16x2_NEON(q0, q1, dst + stride, stride); } -static WEBP_INLINE void Store8x2x2(const uint8x16_t p0, const uint8x16_t q0, - uint8_t* const u, uint8_t* const v, - int stride) { +static WEBP_INLINE void Store8x2x2_NEON(const uint8x16_t p0, + const uint8x16_t q0, + uint8_t* const u, uint8_t* const v, + int stride) { // p0 and q0 contain the u+v samples packed in low/high halves. vst1_u8(u - stride, vget_low_u8(p0)); vst1_u8(u, vget_low_u8(q0)); @@ -312,13 +295,15 @@ static WEBP_INLINE void Store8x2x2(const uint8x16_t p0, const uint8x16_t q0, vst1_u8(v, vget_high_u8(q0)); } -static WEBP_INLINE void Store8x4x2(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const u, uint8_t* const v, - int stride) { +static WEBP_INLINE void Store8x4x2_NEON(const uint8x16_t p1, + const uint8x16_t p0, + const uint8x16_t q0, + const uint8x16_t q1, + uint8_t* const u, uint8_t* const v, + int stride) { // The p1...q1 registers contain the u+v samples packed in low/high halves. - Store8x2x2(p1, p0, u - stride, v - stride, stride); - Store8x2x2(q0, q1, u + stride, v + stride, stride); + Store8x2x2_NEON(p1, p0, u - stride, v - stride, stride); + Store8x2x2_NEON(q0, q1, u + stride, v + stride, stride); } #if !defined(WORK_AROUND_GCC) @@ -329,11 +314,10 @@ static WEBP_INLINE void Store8x4x2(const uint8x16_t p1, const uint8x16_t p0, (DST) += stride; \ } while (0) -static WEBP_INLINE void Store6x8x2(const uint8x16_t p2, const uint8x16_t p1, - const uint8x16_t p0, const uint8x16_t q0, - const uint8x16_t q1, const uint8x16_t q2, - uint8_t* u, uint8_t* v, - int stride) { +static WEBP_INLINE void Store6x8x2_NEON( + const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t q2, + uint8_t* u, uint8_t* v, int stride) { uint8x8x3_t u0, u1, v0, v1; INIT_VECTOR3(u0, vget_low_u8(p2), vget_low_u8(p1), vget_low_u8(p0)); INIT_VECTOR3(u1, vget_low_u8(q0), vget_low_u8(q1), vget_low_u8(q2)); @@ -358,10 +342,12 @@ static WEBP_INLINE void Store6x8x2(const uint8x16_t p2, const uint8x16_t p1, } #undef STORE6_LANE -static WEBP_INLINE void Store4x8x2(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - uint8_t* const u, uint8_t* const v, - int stride) { +static WEBP_INLINE void Store4x8x2_NEON(const uint8x16_t p1, + const uint8x16_t p0, + const uint8x16_t q0, + const uint8x16_t q1, + uint8_t* const u, uint8_t* const v, + int stride) { uint8x8x4_t u0, v0; INIT_VECTOR4(u0, vget_low_u8(p1), vget_low_u8(p0), @@ -390,15 +376,15 @@ static WEBP_INLINE void Store4x8x2(const uint8x16_t p1, const uint8x16_t p0, #endif // !WORK_AROUND_GCC // Zero extend 'v' to an int16x8_t. -static WEBP_INLINE int16x8_t ConvertU8ToS16(uint8x8_t v) { +static WEBP_INLINE int16x8_t ConvertU8ToS16_NEON(uint8x8_t v) { return vreinterpretq_s16_u16(vmovl_u8(v)); } // Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result // to the corresponding rows of 'dst'. -static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst, - const int16x8_t dst01, - const int16x8_t dst23) { +static WEBP_INLINE void SaturateAndStore4x4_NEON(uint8_t* const dst, + const int16x8_t dst01, + const int16x8_t dst23) { // Unsigned saturate to 8b. const uint8x8_t dst01_u8 = vqmovun_s16(dst01); const uint8x8_t dst23_u8 = vqmovun_s16(dst23); @@ -410,8 +396,9 @@ static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst, vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1); } -static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23, - uint8_t* const dst) { +static WEBP_INLINE void Add4x4_NEON(const int16x8_t row01, + const int16x8_t row23, + uint8_t* const dst) { uint32x2_t dst01 = vdup_n_u32(0); uint32x2_t dst23 = vdup_n_u32(0); @@ -423,23 +410,23 @@ static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23, { // Convert to 16b. - const int16x8_t dst01_s16 = ConvertU8ToS16(vreinterpret_u8_u32(dst01)); - const int16x8_t dst23_s16 = ConvertU8ToS16(vreinterpret_u8_u32(dst23)); + const int16x8_t dst01_s16 = ConvertU8ToS16_NEON(vreinterpret_u8_u32(dst01)); + const int16x8_t dst23_s16 = ConvertU8ToS16_NEON(vreinterpret_u8_u32(dst23)); // Descale with rounding. const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3); const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3); // Add the inverse transform. - SaturateAndStore4x4(dst, out01, out23); + SaturateAndStore4x4_NEON(dst, out01, out23); } } //----------------------------------------------------------------------------- // Simple In-loop filtering (Paragraph 15.2) -static uint8x16_t NeedsFilter(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - int thresh) { +static uint8x16_t NeedsFilter_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + int thresh) { const uint8x16_t thresh_v = vdupq_n_u8((uint8_t)thresh); const uint8x16_t a_p0_q0 = vabdq_u8(p0, q0); // abs(p0-q0) const uint8x16_t a_p1_q1 = vabdq_u8(p1, q1); // abs(p1-q1) @@ -450,18 +437,18 @@ static uint8x16_t NeedsFilter(const uint8x16_t p1, const uint8x16_t p0, return mask; } -static int8x16_t FlipSign(const uint8x16_t v) { +static int8x16_t FlipSign_NEON(const uint8x16_t v) { const uint8x16_t sign_bit = vdupq_n_u8(0x80); return vreinterpretq_s8_u8(veorq_u8(v, sign_bit)); } -static uint8x16_t FlipSignBack(const int8x16_t v) { +static uint8x16_t FlipSignBack_NEON(const int8x16_t v) { const int8x16_t sign_bit = vdupq_n_s8(0x80); return vreinterpretq_u8_s8(veorq_s8(v, sign_bit)); } -static int8x16_t GetBaseDelta(const int8x16_t p1, const int8x16_t p0, - const int8x16_t q0, const int8x16_t q1) { +static int8x16_t GetBaseDelta_NEON(const int8x16_t p1, const int8x16_t p0, + const int8x16_t q0, const int8x16_t q1) { const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0) const int8x16_t p1_q1 = vqsubq_s8(p1, q1); // (p1-q1) const int8x16_t s1 = vqaddq_s8(p1_q1, q0_p0); // (p1-q1) + 1 * (q0 - p0) @@ -470,7 +457,7 @@ static int8x16_t GetBaseDelta(const int8x16_t p1, const int8x16_t p0, return s3; } -static int8x16_t GetBaseDelta0(const int8x16_t p0, const int8x16_t q0) { +static int8x16_t GetBaseDelta0_NEON(const int8x16_t p0, const int8x16_t q0) { const int8x16_t q0_p0 = vqsubq_s8(q0, p0); // (q0-p0) const int8x16_t s1 = vqaddq_s8(q0_p0, q0_p0); // 2 * (q0 - p0) const int8x16_t s2 = vqaddq_s8(q0_p0, s1); // 3 * (q0 - p0) @@ -479,9 +466,10 @@ static int8x16_t GetBaseDelta0(const int8x16_t p0, const int8x16_t q0) { //------------------------------------------------------------------------------ -static void ApplyFilter2NoFlip(const int8x16_t p0s, const int8x16_t q0s, - const int8x16_t delta, - int8x16_t* const op0, int8x16_t* const oq0) { +static void ApplyFilter2NoFlip_NEON(const int8x16_t p0s, const int8x16_t q0s, + const int8x16_t delta, + int8x16_t* const op0, + int8x16_t* const oq0) { const int8x16_t kCst3 = vdupq_n_s8(0x03); const int8x16_t kCst4 = vdupq_n_s8(0x04); const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3); @@ -494,9 +482,9 @@ static void ApplyFilter2NoFlip(const int8x16_t p0s, const int8x16_t q0s, #if defined(WEBP_USE_INTRINSICS) -static void ApplyFilter2(const int8x16_t p0s, const int8x16_t q0s, - const int8x16_t delta, - uint8x16_t* const op0, uint8x16_t* const oq0) { +static void ApplyFilter2_NEON(const int8x16_t p0s, const int8x16_t q0s, + const int8x16_t delta, + uint8x16_t* const op0, uint8x16_t* const oq0) { const int8x16_t kCst3 = vdupq_n_s8(0x03); const int8x16_t kCst4 = vdupq_n_s8(0x04); const int8x16_t delta_p3 = vqaddq_s8(delta, kCst3); @@ -505,45 +493,66 @@ static void ApplyFilter2(const int8x16_t p0s, const int8x16_t q0s, const int8x16_t delta4 = vshrq_n_s8(delta_p4, 3); const int8x16_t sp0 = vqaddq_s8(p0s, delta3); const int8x16_t sq0 = vqsubq_s8(q0s, delta4); - *op0 = FlipSignBack(sp0); - *oq0 = FlipSignBack(sq0); + *op0 = FlipSignBack_NEON(sp0); + *oq0 = FlipSignBack_NEON(sq0); } -static void DoFilter2(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - const uint8x16_t mask, - uint8x16_t* const op0, uint8x16_t* const oq0) { - const int8x16_t p1s = FlipSign(p1); - const int8x16_t p0s = FlipSign(p0); - const int8x16_t q0s = FlipSign(q0); - const int8x16_t q1s = FlipSign(q1); - const int8x16_t delta0 = GetBaseDelta(p1s, p0s, q0s, q1s); +static void DoFilter2_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + const uint8x16_t mask, + uint8x16_t* const op0, uint8x16_t* const oq0) { + const int8x16_t p1s = FlipSign_NEON(p1); + const int8x16_t p0s = FlipSign_NEON(p0); + const int8x16_t q0s = FlipSign_NEON(q0); + const int8x16_t q1s = FlipSign_NEON(q1); + const int8x16_t delta0 = GetBaseDelta_NEON(p1s, p0s, q0s, q1s); const int8x16_t delta1 = vandq_s8(delta0, vreinterpretq_s8_u8(mask)); - ApplyFilter2(p0s, q0s, delta1, op0, oq0); + ApplyFilter2_NEON(p0s, q0s, delta1, op0, oq0); } -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { +static void SimpleVFilter16_NEON(uint8_t* p, int stride, int thresh) { uint8x16_t p1, p0, q0, q1, op0, oq0; - Load16x4(p, stride, &p1, &p0, &q0, &q1); + Load16x4_NEON(p, stride, &p1, &p0, &q0, &q1); { - const uint8x16_t mask = NeedsFilter(p1, p0, q0, q1, thresh); - DoFilter2(p1, p0, q0, q1, mask, &op0, &oq0); + const uint8x16_t mask = NeedsFilter_NEON(p1, p0, q0, q1, thresh); + DoFilter2_NEON(p1, p0, q0, q1, mask, &op0, &oq0); } - Store16x2(op0, oq0, p, stride); + Store16x2_NEON(op0, oq0, p, stride); } -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { +static void SimpleHFilter16_NEON(uint8_t* p, int stride, int thresh) { uint8x16_t p1, p0, q0, q1, oq0, op0; - Load4x16(p, stride, &p1, &p0, &q0, &q1); + Load4x16_NEON(p, stride, &p1, &p0, &q0, &q1); { - const uint8x16_t mask = NeedsFilter(p1, p0, q0, q1, thresh); - DoFilter2(p1, p0, q0, q1, mask, &op0, &oq0); + const uint8x16_t mask = NeedsFilter_NEON(p1, p0, q0, q1, thresh); + DoFilter2_NEON(p1, p0, q0, q1, mask, &op0, &oq0); } - Store2x16(op0, oq0, p, stride); + Store2x16_NEON(op0, oq0, p, stride); } #else +// Load/Store vertical edge +#define LOAD8x4(c1, c2, c3, c4, b1, b2, stride) \ + "vld4.8 {" #c1 "[0]," #c2 "[0]," #c3 "[0]," #c4 "[0]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[1]," #c2 "[1]," #c3 "[1]," #c4 "[1]}," #b2 "," #stride "\n" \ + "vld4.8 {" #c1 "[2]," #c2 "[2]," #c3 "[2]," #c4 "[2]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[3]," #c2 "[3]," #c3 "[3]," #c4 "[3]}," #b2 "," #stride "\n" \ + "vld4.8 {" #c1 "[4]," #c2 "[4]," #c3 "[4]," #c4 "[4]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[5]," #c2 "[5]," #c3 "[5]," #c4 "[5]}," #b2 "," #stride "\n" \ + "vld4.8 {" #c1 "[6]," #c2 "[6]," #c3 "[6]," #c4 "[6]}," #b1 "," #stride "\n" \ + "vld4.8 {" #c1 "[7]," #c2 "[7]," #c3 "[7]," #c4 "[7]}," #b2 "," #stride "\n" + +#define STORE8x2(c1, c2, p, stride) \ + "vst2.8 {" #c1 "[0], " #c2 "[0]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[1], " #c2 "[1]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[2], " #c2 "[2]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[3], " #c2 "[3]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[4], " #c2 "[4]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[5], " #c2 "[5]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[6], " #c2 "[6]}," #p "," #stride " \n" \ + "vst2.8 {" #c1 "[7], " #c2 "[7]}," #p "," #stride " \n" + #define QRegs "q0", "q1", "q2", "q3", \ "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15" @@ -592,7 +601,7 @@ static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { DO_SIMPLE_FILTER(p0, q0, q9) /* apply filter */ \ FLIP_SIGN_BIT2(p0, q0, q10) -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { +static void SimpleVFilter16_NEON(uint8_t* p, int stride, int thresh) { __asm__ volatile ( "sub %[p], %[p], %[stride], lsl #1 \n" // p -= 2 * stride @@ -613,7 +622,7 @@ static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { ); } -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { +static void SimpleHFilter16_NEON(uint8_t* p, int stride, int thresh) { __asm__ volatile ( "sub r4, %[p], #2 \n" // base1 = p - 2 "lsl r6, %[stride], #1 \n" // r6 = 2 * stride @@ -639,30 +648,33 @@ static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { ); } +#undef LOAD8x4 +#undef STORE8x2 + #endif // WEBP_USE_INTRINSICS -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { +static void SimpleVFilter16i_NEON(uint8_t* p, int stride, int thresh) { uint32_t k; for (k = 3; k != 0; --k) { p += 4 * stride; - SimpleVFilter16(p, stride, thresh); + SimpleVFilter16_NEON(p, stride, thresh); } } -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { +static void SimpleHFilter16i_NEON(uint8_t* p, int stride, int thresh) { uint32_t k; for (k = 3; k != 0; --k) { p += 4; - SimpleHFilter16(p, stride, thresh); + SimpleHFilter16_NEON(p, stride, thresh); } } //------------------------------------------------------------------------------ // Complex In-loop filtering (Paragraph 15.3) -static uint8x16_t NeedsHev(const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - int hev_thresh) { +static uint8x16_t NeedsHev_NEON(const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + int hev_thresh) { const uint8x16_t hev_thresh_v = vdupq_n_u8((uint8_t)hev_thresh); const uint8x16_t a_p1_p0 = vabdq_u8(p1, p0); // abs(p1 - p0) const uint8x16_t a_q1_q0 = vabdq_u8(q1, q0); // abs(q1 - q0) @@ -671,11 +683,11 @@ static uint8x16_t NeedsHev(const uint8x16_t p1, const uint8x16_t p0, return mask; } -static uint8x16_t NeedsFilter2(const uint8x16_t p3, const uint8x16_t p2, - const uint8x16_t p1, const uint8x16_t p0, - const uint8x16_t q0, const uint8x16_t q1, - const uint8x16_t q2, const uint8x16_t q3, - int ithresh, int thresh) { +static uint8x16_t NeedsFilter2_NEON(const uint8x16_t p3, const uint8x16_t p2, + const uint8x16_t p1, const uint8x16_t p0, + const uint8x16_t q0, const uint8x16_t q1, + const uint8x16_t q2, const uint8x16_t q3, + int ithresh, int thresh) { const uint8x16_t ithresh_v = vdupq_n_u8((uint8_t)ithresh); const uint8x16_t a_p3_p2 = vabdq_u8(p3, p2); // abs(p3 - p2) const uint8x16_t a_p2_p1 = vabdq_u8(p2, p1); // abs(p2 - p1) @@ -689,14 +701,14 @@ static uint8x16_t NeedsFilter2(const uint8x16_t p3, const uint8x16_t p2, const uint8x16_t max12 = vmaxq_u8(max1, max2); const uint8x16_t max123 = vmaxq_u8(max12, max3); const uint8x16_t mask2 = vcgeq_u8(ithresh_v, max123); - const uint8x16_t mask1 = NeedsFilter(p1, p0, q0, q1, thresh); + const uint8x16_t mask1 = NeedsFilter_NEON(p1, p0, q0, q1, thresh); const uint8x16_t mask = vandq_u8(mask1, mask2); return mask; } // 4-points filter -static void ApplyFilter4( +static void ApplyFilter4_NEON( const int8x16_t p1, const int8x16_t p0, const int8x16_t q0, const int8x16_t q1, const int8x16_t delta0, @@ -709,47 +721,47 @@ static void ApplyFilter4( const int8x16_t a1 = vshrq_n_s8(delta1, 3); const int8x16_t a2 = vshrq_n_s8(delta2, 3); const int8x16_t a3 = vrshrq_n_s8(a1, 1); // a3 = (a1 + 1) >> 1 - *op0 = FlipSignBack(vqaddq_s8(p0, a2)); // clip(p0 + a2) - *oq0 = FlipSignBack(vqsubq_s8(q0, a1)); // clip(q0 - a1) - *op1 = FlipSignBack(vqaddq_s8(p1, a3)); // clip(p1 + a3) - *oq1 = FlipSignBack(vqsubq_s8(q1, a3)); // clip(q1 - a3) + *op0 = FlipSignBack_NEON(vqaddq_s8(p0, a2)); // clip(p0 + a2) + *oq0 = FlipSignBack_NEON(vqsubq_s8(q0, a1)); // clip(q0 - a1) + *op1 = FlipSignBack_NEON(vqaddq_s8(p1, a3)); // clip(p1 + a3) + *oq1 = FlipSignBack_NEON(vqsubq_s8(q1, a3)); // clip(q1 - a3) } -static void DoFilter4( +static void DoFilter4_NEON( const uint8x16_t p1, const uint8x16_t p0, const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t mask, const uint8x16_t hev_mask, uint8x16_t* const op1, uint8x16_t* const op0, uint8x16_t* const oq0, uint8x16_t* const oq1) { // This is a fused version of DoFilter2() calling ApplyFilter2 directly - const int8x16_t p1s = FlipSign(p1); - int8x16_t p0s = FlipSign(p0); - int8x16_t q0s = FlipSign(q0); - const int8x16_t q1s = FlipSign(q1); + const int8x16_t p1s = FlipSign_NEON(p1); + int8x16_t p0s = FlipSign_NEON(p0); + int8x16_t q0s = FlipSign_NEON(q0); + const int8x16_t q1s = FlipSign_NEON(q1); const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask); // do_filter2 part (simple loopfilter on pixels with hev) { - const int8x16_t delta = GetBaseDelta(p1s, p0s, q0s, q1s); + const int8x16_t delta = GetBaseDelta_NEON(p1s, p0s, q0s, q1s); const int8x16_t simple_lf_delta = vandq_s8(delta, vreinterpretq_s8_u8(simple_lf_mask)); - ApplyFilter2NoFlip(p0s, q0s, simple_lf_delta, &p0s, &q0s); + ApplyFilter2NoFlip_NEON(p0s, q0s, simple_lf_delta, &p0s, &q0s); } // do_filter4 part (complex loopfilter on pixels without hev) { - const int8x16_t delta0 = GetBaseDelta0(p0s, q0s); + const int8x16_t delta0 = GetBaseDelta0_NEON(p0s, q0s); // we use: (mask & hev_mask) ^ mask = mask & !hev_mask const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask); const int8x16_t complex_lf_delta = vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask)); - ApplyFilter4(p1s, p0s, q0s, q1s, complex_lf_delta, op1, op0, oq0, oq1); + ApplyFilter4_NEON(p1s, p0s, q0s, q1s, complex_lf_delta, op1, op0, oq0, oq1); } } // 6-points filter -static void ApplyFilter6( +static void ApplyFilter6_NEON( const int8x16_t p2, const int8x16_t p1, const int8x16_t p0, const int8x16_t q0, const int8x16_t q1, const int8x16_t q2, const int8x16_t delta, @@ -778,35 +790,35 @@ static void ApplyFilter6( const int8x16_t a2 = vcombine_s8(a2_lo, a2_hi); const int8x16_t a3 = vcombine_s8(a3_lo, a3_hi); - *op0 = FlipSignBack(vqaddq_s8(p0, a1)); // clip(p0 + a1) - *oq0 = FlipSignBack(vqsubq_s8(q0, a1)); // clip(q0 - q1) - *oq1 = FlipSignBack(vqsubq_s8(q1, a2)); // clip(q1 - a2) - *op1 = FlipSignBack(vqaddq_s8(p1, a2)); // clip(p1 + a2) - *oq2 = FlipSignBack(vqsubq_s8(q2, a3)); // clip(q2 - a3) - *op2 = FlipSignBack(vqaddq_s8(p2, a3)); // clip(p2 + a3) + *op0 = FlipSignBack_NEON(vqaddq_s8(p0, a1)); // clip(p0 + a1) + *oq0 = FlipSignBack_NEON(vqsubq_s8(q0, a1)); // clip(q0 - q1) + *oq1 = FlipSignBack_NEON(vqsubq_s8(q1, a2)); // clip(q1 - a2) + *op1 = FlipSignBack_NEON(vqaddq_s8(p1, a2)); // clip(p1 + a2) + *oq2 = FlipSignBack_NEON(vqsubq_s8(q2, a3)); // clip(q2 - a3) + *op2 = FlipSignBack_NEON(vqaddq_s8(p2, a3)); // clip(p2 + a3) } -static void DoFilter6( +static void DoFilter6_NEON( const uint8x16_t p2, const uint8x16_t p1, const uint8x16_t p0, const uint8x16_t q0, const uint8x16_t q1, const uint8x16_t q2, const uint8x16_t mask, const uint8x16_t hev_mask, uint8x16_t* const op2, uint8x16_t* const op1, uint8x16_t* const op0, uint8x16_t* const oq0, uint8x16_t* const oq1, uint8x16_t* const oq2) { // This is a fused version of DoFilter2() calling ApplyFilter2 directly - const int8x16_t p2s = FlipSign(p2); - const int8x16_t p1s = FlipSign(p1); - int8x16_t p0s = FlipSign(p0); - int8x16_t q0s = FlipSign(q0); - const int8x16_t q1s = FlipSign(q1); - const int8x16_t q2s = FlipSign(q2); + const int8x16_t p2s = FlipSign_NEON(p2); + const int8x16_t p1s = FlipSign_NEON(p1); + int8x16_t p0s = FlipSign_NEON(p0); + int8x16_t q0s = FlipSign_NEON(q0); + const int8x16_t q1s = FlipSign_NEON(q1); + const int8x16_t q2s = FlipSign_NEON(q2); const uint8x16_t simple_lf_mask = vandq_u8(mask, hev_mask); - const int8x16_t delta0 = GetBaseDelta(p1s, p0s, q0s, q1s); + const int8x16_t delta0 = GetBaseDelta_NEON(p1s, p0s, q0s, q1s); // do_filter2 part (simple loopfilter on pixels with hev) { const int8x16_t simple_lf_delta = vandq_s8(delta0, vreinterpretq_s8_u8(simple_lf_mask)); - ApplyFilter2NoFlip(p0s, q0s, simple_lf_delta, &p0s, &q0s); + ApplyFilter2NoFlip_NEON(p0s, q0s, simple_lf_delta, &p0s, &q0s); } // do_filter6 part (complex loopfilter on pixels without hev) @@ -815,65 +827,65 @@ static void DoFilter6( const uint8x16_t complex_lf_mask = veorq_u8(simple_lf_mask, mask); const int8x16_t complex_lf_delta = vandq_s8(delta0, vreinterpretq_s8_u8(complex_lf_mask)); - ApplyFilter6(p2s, p1s, p0s, q0s, q1s, q2s, complex_lf_delta, - op2, op1, op0, oq0, oq1, oq2); + ApplyFilter6_NEON(p2s, p1s, p0s, q0s, q1s, q2s, complex_lf_delta, + op2, op1, op0, oq0, oq1, oq2); } } // on macroblock edges -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { +static void VFilter16_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load16x8(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + Load16x8_NEON(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store16x2(op2, op1, p - 2 * stride, stride); - Store16x2(op0, oq0, p + 0 * stride, stride); - Store16x2(oq1, oq2, p + 2 * stride, stride); + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store16x2_NEON(op2, op1, p - 2 * stride, stride); + Store16x2_NEON(op0, oq0, p + 0 * stride, stride); + Store16x2_NEON(oq1, oq2, p + 2 * stride, stride); } } -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { +static void HFilter16_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load8x16(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + Load8x16_NEON(p, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store2x16(op2, op1, p - 2, stride); - Store2x16(op0, oq0, p + 0, stride); - Store2x16(oq1, oq2, p + 2, stride); + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store2x16_NEON(op2, op1, p - 2, stride); + Store2x16_NEON(op0, oq0, p + 0, stride); + Store2x16_NEON(oq1, oq2, p + 2, stride); } } // on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { +static void VFilter16i_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { uint32_t k; uint8x16_t p3, p2, p1, p0; - Load16x4(p + 2 * stride, stride, &p3, &p2, &p1, &p0); + Load16x4_NEON(p + 2 * stride, stride, &p3, &p2, &p1, &p0); for (k = 3; k != 0; --k) { uint8x16_t q0, q1, q2, q3; p += 4 * stride; - Load16x4(p + 2 * stride, stride, &q0, &q1, &q2, &q3); + Load16x4_NEON(p + 2 * stride, stride, &q0, &q1, &q2, &q3); { const uint8x16_t mask = - NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); + NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); // p3 and p2 are not just temporary variables here: they will be // re-used for next span. And q2/q3 will become p1/p0 accordingly. - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); - Store16x4(p1, p0, p3, p2, p, stride); + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); + Store16x4_NEON(p1, p0, p3, p2, p, stride); p1 = q2; p0 = q3; } @@ -881,21 +893,21 @@ static void VFilter16i(uint8_t* p, int stride, } #if !defined(WORK_AROUND_GCC) -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { +static void HFilter16i_NEON(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { uint32_t k; uint8x16_t p3, p2, p1, p0; - Load4x16(p + 2, stride, &p3, &p2, &p1, &p0); + Load4x16_NEON(p + 2, stride, &p3, &p2, &p1, &p0); for (k = 3; k != 0; --k) { uint8x16_t q0, q1, q2, q3; p += 4; - Load4x16(p + 2, stride, &q0, &q1, &q2, &q3); + Load4x16_NEON(p + 2, stride, &q0, &q1, &q2, &q3); { const uint8x16_t mask = - NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); - Store4x16(p1, p0, p3, p2, p, stride); + NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &p1, &p0, &p3, &p2); + Store4x16_NEON(p1, p0, p3, p2, p, stride); p1 = q2; p0 = q3; } @@ -904,67 +916,67 @@ static void HFilter16i(uint8_t* p, int stride, #endif // !WORK_AROUND_GCC // 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { +static void VFilter8_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load8x8x2(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + Load8x8x2_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store8x2x2(op2, op1, u - 2 * stride, v - 2 * stride, stride); - Store8x2x2(op0, oq0, u + 0 * stride, v + 0 * stride, stride); - Store8x2x2(oq1, oq2, u + 2 * stride, v + 2 * stride, stride); + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store8x2x2_NEON(op2, op1, u - 2 * stride, v - 2 * stride, stride); + Store8x2x2_NEON(op0, oq0, u + 0 * stride, v + 0 * stride, stride); + Store8x2x2_NEON(oq1, oq2, u + 2 * stride, v + 2 * stride, stride); } } -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { +static void VFilter8i_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; u += 4 * stride; v += 4 * stride; - Load8x8x2(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + Load8x8x2_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); uint8x16_t op1, op0, oq0, oq1; - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); - Store8x4x2(op1, op0, oq0, oq1, u, v, stride); + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); + Store8x4x2_NEON(op1, op0, oq0, oq1, u, v, stride); } } #if !defined(WORK_AROUND_GCC) -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { +static void HFilter8_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; - Load8x8x2T(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + Load8x8x2T_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); uint8x16_t op2, op1, op0, oq0, oq1, oq2; - DoFilter6(p2, p1, p0, q0, q1, q2, mask, hev_mask, - &op2, &op1, &op0, &oq0, &oq1, &oq2); - Store6x8x2(op2, op1, op0, oq0, oq1, oq2, u, v, stride); + DoFilter6_NEON(p2, p1, p0, q0, q1, q2, mask, hev_mask, + &op2, &op1, &op0, &oq0, &oq1, &oq2); + Store6x8x2_NEON(op2, op1, op0, oq0, oq1, oq2, u, v, stride); } } -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { +static void HFilter8i_NEON(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { uint8x16_t p3, p2, p1, p0, q0, q1, q2, q3; u += 4; v += 4; - Load8x8x2T(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); + Load8x8x2T_NEON(u, v, stride, &p3, &p2, &p1, &p0, &q0, &q1, &q2, &q3); { - const uint8x16_t mask = NeedsFilter2(p3, p2, p1, p0, q0, q1, q2, q3, - ithresh, thresh); - const uint8x16_t hev_mask = NeedsHev(p1, p0, q0, q1, hev_thresh); + const uint8x16_t mask = NeedsFilter2_NEON(p3, p2, p1, p0, q0, q1, q2, q3, + ithresh, thresh); + const uint8x16_t hev_mask = NeedsHev_NEON(p1, p0, q0, q1, hev_thresh); uint8x16_t op1, op0, oq0, oq1; - DoFilter4(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); - Store4x8x2(op1, op0, oq0, oq1, u, v, stride); + DoFilter4_NEON(p1, p0, q0, q1, mask, hev_mask, &op1, &op0, &oq0, &oq1); + Store4x8x2_NEON(op1, op0, oq0, oq1, u, v, stride); } } #endif // !WORK_AROUND_GCC @@ -992,8 +1004,9 @@ static const int16_t kC1 = 20091; static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. #if defined(WEBP_USE_INTRINSICS) -static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1, - int16x8x2_t* const out) { +static WEBP_INLINE void Transpose8x2_NEON(const int16x8_t in0, + const int16x8_t in1, + int16x8x2_t* const out) { // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1 // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3 const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ... @@ -1001,7 +1014,7 @@ static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1, *out = vzipq_s16(tmp0.val[0], tmp0.val[1]); } -static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) { +static WEBP_INLINE void TransformPass_NEON(int16x8x2_t* const rows) { // {rows} = in0 | in4 // in8 | in12 // B1 = in4 | in12 @@ -1024,20 +1037,20 @@ static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) { const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp)); - Transpose8x2(E0, E1, rows); + Transpose8x2_NEON(E0, E1, rows); } -static void TransformOne(const int16_t* in, uint8_t* dst) { +static void TransformOne_NEON(const int16_t* in, uint8_t* dst) { int16x8x2_t rows; INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8)); - TransformPass(&rows); - TransformPass(&rows); - Add4x4(rows.val[0], rows.val[1], dst); + TransformPass_NEON(&rows); + TransformPass_NEON(&rows); + Add4x4_NEON(rows.val[0], rows.val[1], dst); } #else -static void TransformOne(const int16_t* in, uint8_t* dst) { +static void TransformOne_NEON(const int16_t* in, uint8_t* dst) { const int kBPS = BPS; // kC1, kC2. Padded because vld1.16 loads 8 bytes const int16_t constants[4] = { kC1, kC2, 0, 0 }; @@ -1170,16 +1183,16 @@ static void TransformOne(const int16_t* in, uint8_t* dst) { #endif // WEBP_USE_INTRINSICS -static void TransformTwo(const int16_t* in, uint8_t* dst, int do_two) { - TransformOne(in, dst); +static void TransformTwo_NEON(const int16_t* in, uint8_t* dst, int do_two) { + TransformOne_NEON(in, dst); if (do_two) { - TransformOne(in + 16, dst + 4); + TransformOne_NEON(in + 16, dst + 4); } } -static void TransformDC(const int16_t* in, uint8_t* dst) { +static void TransformDC_NEON(const int16_t* in, uint8_t* dst) { const int16x8_t DC = vdupq_n_s16(in[0]); - Add4x4(DC, DC, dst); + Add4x4_NEON(DC, DC, dst); } //------------------------------------------------------------------------------ @@ -1191,7 +1204,7 @@ static void TransformDC(const int16_t* in, uint8_t* dst) { *dst = vgetq_lane_s32(rows.val[3], col); (dst) += 16; \ } while (0) -static void TransformWHT(const int16_t* in, int16_t* out) { +static void TransformWHT_NEON(const int16_t* in, int16_t* out) { int32x4x4_t tmp; { @@ -1209,7 +1222,7 @@ static void TransformWHT(const int16_t* in, int16_t* out) { tmp.val[2] = vsubq_s32(a0, a1); tmp.val[3] = vsubq_s32(a3, a2); // Arrange the temporary results column-wise. - tmp = Transpose4x4(tmp); + tmp = Transpose4x4_NEON(tmp); } { @@ -1243,7 +1256,7 @@ static void TransformWHT(const int16_t* in, int16_t* out) { //------------------------------------------------------------------------------ #define MUL(a, b) (((a) * (b)) >> 16) -static void TransformAC3(const int16_t* in, uint8_t* dst) { +static void TransformAC3_NEON(const int16_t* in, uint8_t* dst) { static const int kC1_full = 20091 + (1 << 16); static const int kC2_full = 35468; const int16x4_t A = vld1_dup_s16(in); @@ -1259,14 +1272,14 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) { const int16x4_t B = vqadd_s16(A, CD); const int16x8_t m0_m1 = vcombine_s16(vqadd_s16(B, d4), vqadd_s16(B, c4)); const int16x8_t m2_m3 = vcombine_s16(vqsub_s16(B, c4), vqsub_s16(B, d4)); - Add4x4(m0_m1, m2_m3, dst); + Add4x4_NEON(m0_m1, m2_m3, dst); } #undef MUL //------------------------------------------------------------------------------ // 4x4 -static void DC4(uint8_t* dst) { // DC +static void DC4_NEON(uint8_t* dst) { // DC const uint8x8_t A = vld1_u8(dst - BPS); // top row const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top const uint16x4_t p1 = vpadd_u16(p0, p0); @@ -1287,17 +1300,17 @@ static void DC4(uint8_t* dst) { // DC } // TrueMotion (4x4 + 8x8) -static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { +static WEBP_INLINE void TrueMotion_NEON(uint8_t* dst, int size) { const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]' const uint8x8_t T = vld1_u8(dst - BPS); // top row 'A[0..3]' const int16x8_t d = vreinterpretq_s16_u16(vsubl_u8(T, TL)); // A[c] - A[-1] int y; for (y = 0; y < size; y += 4) { // left edge - const int16x8_t L0 = ConvertU8ToS16(vld1_dup_u8(dst + 0 * BPS - 1)); - const int16x8_t L1 = ConvertU8ToS16(vld1_dup_u8(dst + 1 * BPS - 1)); - const int16x8_t L2 = ConvertU8ToS16(vld1_dup_u8(dst + 2 * BPS - 1)); - const int16x8_t L3 = ConvertU8ToS16(vld1_dup_u8(dst + 3 * BPS - 1)); + const int16x8_t L0 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 0 * BPS - 1)); + const int16x8_t L1 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 1 * BPS - 1)); + const int16x8_t L2 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 2 * BPS - 1)); + const int16x8_t L3 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 3 * BPS - 1)); const int16x8_t r0 = vaddq_s16(L0, d); // L[r] + A[c] - A[-1] const int16x8_t r1 = vaddq_s16(L1, d); const int16x8_t r2 = vaddq_s16(L2, d); @@ -1322,9 +1335,9 @@ static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { } } -static void TM4(uint8_t* dst) { TrueMotion(dst, 4); } +static void TM4_NEON(uint8_t* dst) { TrueMotion_NEON(dst, 4); } -static void VE4(uint8_t* dst) { // vertical +static void VE4_NEON(uint8_t* dst) { // vertical // NB: avoid vld1_u64 here as an alignment hint may be added -> SIGBUS. const uint64x1_t A0 = vreinterpret_u64_u8(vld1_u8(dst - BPS - 1)); // top row const uint64x1_t A1 = vshr_n_u64(A0, 8); @@ -1340,7 +1353,7 @@ static void VE4(uint8_t* dst) { // vertical } } -static void RD4(uint8_t* dst) { // Down-right +static void RD4_NEON(uint8_t* dst) { // Down-right const uint8x8_t XABCD_u8 = vld1_u8(dst - BPS - 1); const uint64x1_t XABCD = vreinterpret_u64_u8(XABCD_u8); const uint64x1_t ____XABC = vshl_n_u64(XABCD, 32); @@ -1368,7 +1381,7 @@ static void RD4(uint8_t* dst) { // Down-right vst1_lane_u32((uint32_t*)(dst + 3 * BPS), r3, 0); } -static void LD4(uint8_t* dst) { // Down-left +static void LD4_NEON(uint8_t* dst) { // Down-left // Note using the same shift trick as VE4() is slower here. const uint8x8_t ABCDEFGH = vld1_u8(dst - BPS + 0); const uint8x8_t BCDEFGH0 = vld1_u8(dst - BPS + 1); @@ -1390,7 +1403,7 @@ static void LD4(uint8_t* dst) { // Down-left //------------------------------------------------------------------------------ // Chroma -static void VE8uv(uint8_t* dst) { // vertical +static void VE8uv_NEON(uint8_t* dst) { // vertical const uint8x8_t top = vld1_u8(dst - BPS); int j; for (j = 0; j < 8; ++j) { @@ -1398,7 +1411,7 @@ static void VE8uv(uint8_t* dst) { // vertical } } -static void HE8uv(uint8_t* dst) { // horizontal +static void HE8uv_NEON(uint8_t* dst) { // horizontal int j; for (j = 0; j < 8; ++j) { const uint8x8_t left = vld1_dup_u8(dst - 1); @@ -1407,7 +1420,7 @@ static void HE8uv(uint8_t* dst) { // horizontal } } -static WEBP_INLINE void DC8(uint8_t* dst, int do_top, int do_left) { +static WEBP_INLINE void DC8_NEON(uint8_t* dst, int do_top, int do_left) { uint16x8_t sum_top; uint16x8_t sum_left; uint8x8_t dc0; @@ -1458,17 +1471,17 @@ static WEBP_INLINE void DC8(uint8_t* dst, int do_top, int do_left) { } } -static void DC8uv(uint8_t* dst) { DC8(dst, 1, 1); } -static void DC8uvNoTop(uint8_t* dst) { DC8(dst, 0, 1); } -static void DC8uvNoLeft(uint8_t* dst) { DC8(dst, 1, 0); } -static void DC8uvNoTopLeft(uint8_t* dst) { DC8(dst, 0, 0); } +static void DC8uv_NEON(uint8_t* dst) { DC8_NEON(dst, 1, 1); } +static void DC8uvNoTop_NEON(uint8_t* dst) { DC8_NEON(dst, 0, 1); } +static void DC8uvNoLeft_NEON(uint8_t* dst) { DC8_NEON(dst, 1, 0); } +static void DC8uvNoTopLeft_NEON(uint8_t* dst) { DC8_NEON(dst, 0, 0); } -static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); } +static void TM8uv_NEON(uint8_t* dst) { TrueMotion_NEON(dst, 8); } //------------------------------------------------------------------------------ // 16x16 -static void VE16(uint8_t* dst) { // vertical +static void VE16_NEON(uint8_t* dst) { // vertical const uint8x16_t top = vld1q_u8(dst - BPS); int j; for (j = 0; j < 16; ++j) { @@ -1476,7 +1489,7 @@ static void VE16(uint8_t* dst) { // vertical } } -static void HE16(uint8_t* dst) { // horizontal +static void HE16_NEON(uint8_t* dst) { // horizontal int j; for (j = 0; j < 16; ++j) { const uint8x16_t left = vld1q_dup_u8(dst - 1); @@ -1485,7 +1498,7 @@ static void HE16(uint8_t* dst) { // horizontal } } -static WEBP_INLINE void DC16(uint8_t* dst, int do_top, int do_left) { +static WEBP_INLINE void DC16_NEON(uint8_t* dst, int do_top, int do_left) { uint16x8_t sum_top; uint16x8_t sum_left; uint8x8_t dc0; @@ -1542,12 +1555,12 @@ static WEBP_INLINE void DC16(uint8_t* dst, int do_top, int do_left) { } } -static void DC16TopLeft(uint8_t* dst) { DC16(dst, 1, 1); } -static void DC16NoTop(uint8_t* dst) { DC16(dst, 0, 1); } -static void DC16NoLeft(uint8_t* dst) { DC16(dst, 1, 0); } -static void DC16NoTopLeft(uint8_t* dst) { DC16(dst, 0, 0); } +static void DC16TopLeft_NEON(uint8_t* dst) { DC16_NEON(dst, 1, 1); } +static void DC16NoTop_NEON(uint8_t* dst) { DC16_NEON(dst, 0, 1); } +static void DC16NoLeft_NEON(uint8_t* dst) { DC16_NEON(dst, 1, 0); } +static void DC16NoTopLeft_NEON(uint8_t* dst) { DC16_NEON(dst, 0, 0); } -static void TM16(uint8_t* dst) { +static void TM16_NEON(uint8_t* dst) { const uint8x8_t TL = vld1_dup_u8(dst - BPS - 1); // top-left pixel 'A[-1]' const uint8x16_t T = vld1q_u8(dst - BPS); // top row 'A[0..15]' // A[c] - A[-1] @@ -1556,10 +1569,10 @@ static void TM16(uint8_t* dst) { int y; for (y = 0; y < 16; y += 4) { // left edge - const int16x8_t L0 = ConvertU8ToS16(vld1_dup_u8(dst + 0 * BPS - 1)); - const int16x8_t L1 = ConvertU8ToS16(vld1_dup_u8(dst + 1 * BPS - 1)); - const int16x8_t L2 = ConvertU8ToS16(vld1_dup_u8(dst + 2 * BPS - 1)); - const int16x8_t L3 = ConvertU8ToS16(vld1_dup_u8(dst + 3 * BPS - 1)); + const int16x8_t L0 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 0 * BPS - 1)); + const int16x8_t L1 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 1 * BPS - 1)); + const int16x8_t L2 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 2 * BPS - 1)); + const int16x8_t L3 = ConvertU8ToS16_NEON(vld1_dup_u8(dst + 3 * BPS - 1)); const int16x8_t r0_lo = vaddq_s16(L0, d_lo); // L[r] + A[c] - A[-1] const int16x8_t r1_lo = vaddq_s16(L1, d_lo); const int16x8_t r2_lo = vaddq_s16(L2, d_lo); @@ -1587,49 +1600,49 @@ static void TM16(uint8_t* dst) { extern void VP8DspInitNEON(void); WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitNEON(void) { - VP8Transform = TransformTwo; - VP8TransformAC3 = TransformAC3; - VP8TransformDC = TransformDC; - VP8TransformWHT = TransformWHT; + VP8Transform = TransformTwo_NEON; + VP8TransformAC3 = TransformAC3_NEON; + VP8TransformDC = TransformDC_NEON; + VP8TransformWHT = TransformWHT_NEON; - VP8VFilter16 = VFilter16; - VP8VFilter16i = VFilter16i; - VP8HFilter16 = HFilter16; + VP8VFilter16 = VFilter16_NEON; + VP8VFilter16i = VFilter16i_NEON; + VP8HFilter16 = HFilter16_NEON; #if !defined(WORK_AROUND_GCC) - VP8HFilter16i = HFilter16i; + VP8HFilter16i = HFilter16i_NEON; #endif - VP8VFilter8 = VFilter8; - VP8VFilter8i = VFilter8i; + VP8VFilter8 = VFilter8_NEON; + VP8VFilter8i = VFilter8i_NEON; #if !defined(WORK_AROUND_GCC) - VP8HFilter8 = HFilter8; - VP8HFilter8i = HFilter8i; + VP8HFilter8 = HFilter8_NEON; + VP8HFilter8i = HFilter8i_NEON; #endif - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; + VP8SimpleVFilter16 = SimpleVFilter16_NEON; + VP8SimpleHFilter16 = SimpleHFilter16_NEON; + VP8SimpleVFilter16i = SimpleVFilter16i_NEON; + VP8SimpleHFilter16i = SimpleHFilter16i_NEON; - VP8PredLuma4[0] = DC4; - VP8PredLuma4[1] = TM4; - VP8PredLuma4[2] = VE4; - VP8PredLuma4[4] = RD4; - VP8PredLuma4[6] = LD4; + VP8PredLuma4[0] = DC4_NEON; + VP8PredLuma4[1] = TM4_NEON; + VP8PredLuma4[2] = VE4_NEON; + VP8PredLuma4[4] = RD4_NEON; + VP8PredLuma4[6] = LD4_NEON; - VP8PredLuma16[0] = DC16TopLeft; - VP8PredLuma16[1] = TM16; - VP8PredLuma16[2] = VE16; - VP8PredLuma16[3] = HE16; - VP8PredLuma16[4] = DC16NoTop; - VP8PredLuma16[5] = DC16NoLeft; - VP8PredLuma16[6] = DC16NoTopLeft; + VP8PredLuma16[0] = DC16TopLeft_NEON; + VP8PredLuma16[1] = TM16_NEON; + VP8PredLuma16[2] = VE16_NEON; + VP8PredLuma16[3] = HE16_NEON; + VP8PredLuma16[4] = DC16NoTop_NEON; + VP8PredLuma16[5] = DC16NoLeft_NEON; + VP8PredLuma16[6] = DC16NoTopLeft_NEON; - VP8PredChroma8[0] = DC8uv; - VP8PredChroma8[1] = TM8uv; - VP8PredChroma8[2] = VE8uv; - VP8PredChroma8[3] = HE8uv; - VP8PredChroma8[4] = DC8uvNoTop; - VP8PredChroma8[5] = DC8uvNoLeft; - VP8PredChroma8[6] = DC8uvNoTopLeft; + VP8PredChroma8[0] = DC8uv_NEON; + VP8PredChroma8[1] = TM8uv_NEON; + VP8PredChroma8[2] = VE8uv_NEON; + VP8PredChroma8[3] = HE8uv_NEON; + VP8PredChroma8[4] = DC8uvNoTop_NEON; + VP8PredChroma8[5] = DC8uvNoLeft_NEON; + VP8PredChroma8[6] = DC8uvNoTopLeft_NEON; } #else // !WEBP_USE_NEON diff --git a/3rdparty/libwebp/dsp/dec_sse2.c b/3rdparty/libwebp/src/dsp/dec_sse2.c similarity index 73% rename from 3rdparty/libwebp/dsp/dec_sse2.c rename to 3rdparty/libwebp/src/dsp/dec_sse2.c index 411fb02768..b3840faf3a 100644 --- a/3rdparty/libwebp/dsp/dec_sse2.c +++ b/3rdparty/libwebp/src/dsp/dec_sse2.c @@ -12,23 +12,25 @@ // Author: somnath@google.com (Somnath Banerjee) // cduvivier@google.com (Christian Duvivier) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE2) // The 3-coeff sparse transform in SSE2 is not really faster than the plain-C // one it seems => disable it by default. Uncomment the following to enable: -// #define USE_TRANSFORM_AC3 +#if !defined(USE_TRANSFORM_AC3) +#define USE_TRANSFORM_AC3 0 // ALTERNATE_CODE +#endif #include -#include "./common_sse2.h" -#include "../dec/vp8i_dec.h" -#include "../utils/utils.h" +#include "src/dsp/common_sse2.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // Transforms (Paragraph 14.4) -static void Transform(const int16_t* in, uint8_t* dst, int do_two) { +static void Transform_SSE2(const int16_t* in, uint8_t* dst, int do_two) { // This implementation makes use of 16-bit fixed point versions of two // multiply constants: // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 @@ -193,7 +195,7 @@ static void Transform(const int16_t* in, uint8_t* dst, int do_two) { } } -#if defined(USE_TRANSFORM_AC3) +#if (USE_TRANSFORM_AC3 == 1) #define MUL(a, b) (((a) * (b)) >> 16) static void TransformAC3(const int16_t* in, uint8_t* dst) { static const int kC1 = 20091 + (1 << 16); @@ -248,7 +250,7 @@ static void TransformAC3(const int16_t* in, uint8_t* dst) { _mm_subs_epu8((p), (q))) // Shift each byte of "x" by 3 bits while preserving by the sign bit. -static WEBP_INLINE void SignedShift8b(__m128i* const x) { +static WEBP_INLINE void SignedShift8b_SSE2(__m128i* const x) { const __m128i zero = _mm_setzero_si128(); const __m128i lo_0 = _mm_unpacklo_epi8(zero, *x); const __m128i hi_0 = _mm_unpackhi_epi8(zero, *x); @@ -258,8 +260,8 @@ static WEBP_INLINE void SignedShift8b(__m128i* const x) { } #define FLIP_SIGN_BIT2(a, b) { \ - a = _mm_xor_si128(a, sign_bit); \ - b = _mm_xor_si128(b, sign_bit); \ + (a) = _mm_xor_si128(a, sign_bit); \ + (b) = _mm_xor_si128(b, sign_bit); \ } #define FLIP_SIGN_BIT4(a, b, c, d) { \ @@ -268,11 +270,11 @@ static WEBP_INLINE void SignedShift8b(__m128i* const x) { } // input/output is uint8_t -static WEBP_INLINE void GetNotHEV(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - int hev_thresh, __m128i* const not_hev) { +static WEBP_INLINE void GetNotHEV_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + int hev_thresh, __m128i* const not_hev) { const __m128i zero = _mm_setzero_si128(); const __m128i t_1 = MM_ABS(*p1, *p0); const __m128i t_2 = MM_ABS(*q1, *q0); @@ -285,11 +287,11 @@ static WEBP_INLINE void GetNotHEV(const __m128i* const p1, } // input pixels are int8_t -static WEBP_INLINE void GetBaseDelta(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - __m128i* const delta) { +static WEBP_INLINE void GetBaseDelta_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + __m128i* const delta) { // beware of addition order, for saturation! const __m128i p1_q1 = _mm_subs_epi8(*p1, *q1); // p1 - q1 const __m128i q0_p0 = _mm_subs_epi8(*q0, *p0); // q0 - p0 @@ -300,15 +302,16 @@ static WEBP_INLINE void GetBaseDelta(const __m128i* const p1, } // input and output are int8_t -static WEBP_INLINE void DoSimpleFilter(__m128i* const p0, __m128i* const q0, - const __m128i* const fl) { +static WEBP_INLINE void DoSimpleFilter_SSE2(__m128i* const p0, + __m128i* const q0, + const __m128i* const fl) { const __m128i k3 = _mm_set1_epi8(3); const __m128i k4 = _mm_set1_epi8(4); __m128i v3 = _mm_adds_epi8(*fl, k3); __m128i v4 = _mm_adds_epi8(*fl, k4); - SignedShift8b(&v4); // v4 >> 3 - SignedShift8b(&v3); // v3 >> 3 + SignedShift8b_SSE2(&v4); // v4 >> 3 + SignedShift8b_SSE2(&v3); // v3 >> 3 *q0 = _mm_subs_epi8(*q0, v4); // q0 -= v4 *p0 = _mm_adds_epi8(*p0, v3); // p0 += v3 } @@ -317,9 +320,9 @@ static WEBP_INLINE void DoSimpleFilter(__m128i* const p0, __m128i* const q0, // Update operations: // q = q - delta and p = p + delta; where delta = [(a_hi >> 7), (a_lo >> 7)] // Pixels 'pi' and 'qi' are int8_t on input, uint8_t on output (sign flip). -static WEBP_INLINE void Update2Pixels(__m128i* const pi, __m128i* const qi, - const __m128i* const a0_lo, - const __m128i* const a0_hi) { +static WEBP_INLINE void Update2Pixels_SSE2(__m128i* const pi, __m128i* const qi, + const __m128i* const a0_lo, + const __m128i* const a0_hi) { const __m128i a1_lo = _mm_srai_epi16(*a0_lo, 7); const __m128i a1_hi = _mm_srai_epi16(*a0_hi, 7); const __m128i delta = _mm_packs_epi16(a1_lo, a1_hi); @@ -330,11 +333,11 @@ static WEBP_INLINE void Update2Pixels(__m128i* const pi, __m128i* const qi, } // input pixels are uint8_t -static WEBP_INLINE void NeedsFilter(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - int thresh, __m128i* const mask) { +static WEBP_INLINE void NeedsFilter_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + int thresh, __m128i* const mask) { const __m128i m_thresh = _mm_set1_epi8(thresh); const __m128i t1 = MM_ABS(*p1, *q1); // abs(p1 - q1) const __m128i kFE = _mm_set1_epi8(0xFE); @@ -353,28 +356,29 @@ static WEBP_INLINE void NeedsFilter(const __m128i* const p1, // Edge filtering functions // Applies filter on 2 pixels (p0 and q0) -static WEBP_INLINE void DoFilter2(__m128i* const p1, __m128i* const p0, - __m128i* const q0, __m128i* const q1, - int thresh) { +static WEBP_INLINE void DoFilter2_SSE2(__m128i* const p1, __m128i* const p0, + __m128i* const q0, __m128i* const q1, + int thresh) { __m128i a, mask; const __m128i sign_bit = _mm_set1_epi8(0x80); - // convert p1/q1 to int8_t (for GetBaseDelta) + // convert p1/q1 to int8_t (for GetBaseDelta_SSE2) const __m128i p1s = _mm_xor_si128(*p1, sign_bit); const __m128i q1s = _mm_xor_si128(*q1, sign_bit); - NeedsFilter(p1, p0, q0, q1, thresh, &mask); + NeedsFilter_SSE2(p1, p0, q0, q1, thresh, &mask); FLIP_SIGN_BIT2(*p0, *q0); - GetBaseDelta(&p1s, p0, q0, &q1s, &a); + GetBaseDelta_SSE2(&p1s, p0, q0, &q1s, &a); a = _mm_and_si128(a, mask); // mask filter values we don't care about - DoSimpleFilter(p0, q0, &a); + DoSimpleFilter_SSE2(p0, q0, &a); FLIP_SIGN_BIT2(*p0, *q0); } // Applies filter on 4 pixels (p1, p0, q0 and q1) -static WEBP_INLINE void DoFilter4(__m128i* const p1, __m128i* const p0, - __m128i* const q0, __m128i* const q1, - const __m128i* const mask, int hev_thresh) { +static WEBP_INLINE void DoFilter4_SSE2(__m128i* const p1, __m128i* const p0, + __m128i* const q0, __m128i* const q1, + const __m128i* const mask, + int hev_thresh) { const __m128i zero = _mm_setzero_si128(); const __m128i sign_bit = _mm_set1_epi8(0x80); const __m128i k64 = _mm_set1_epi8(64); @@ -384,7 +388,7 @@ static WEBP_INLINE void DoFilter4(__m128i* const p1, __m128i* const p0, __m128i t1, t2, t3; // compute hev mask - GetNotHEV(p1, p0, q0, q1, hev_thresh, ¬_hev); + GetNotHEV_SSE2(p1, p0, q0, q1, hev_thresh, ¬_hev); // convert to signed values FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1); @@ -399,8 +403,8 @@ static WEBP_INLINE void DoFilter4(__m128i* const p1, __m128i* const p0, t2 = _mm_adds_epi8(t1, k3); // 3 * (q0 - p0) + hev(p1 - q1) + 3 t3 = _mm_adds_epi8(t1, k4); // 3 * (q0 - p0) + hev(p1 - q1) + 4 - SignedShift8b(&t2); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3 - SignedShift8b(&t3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3 + SignedShift8b_SSE2(&t2); // (3 * (q0 - p0) + hev(p1 - q1) + 3) >> 3 + SignedShift8b_SSE2(&t3); // (3 * (q0 - p0) + hev(p1 - q1) + 4) >> 3 *p0 = _mm_adds_epi8(*p0, t2); // p0 += t2 *q0 = _mm_subs_epi8(*q0, t3); // q0 -= t3 FLIP_SIGN_BIT2(*p0, *q0); @@ -417,25 +421,26 @@ static WEBP_INLINE void DoFilter4(__m128i* const p1, __m128i* const p0, } // Applies filter on 6 pixels (p2, p1, p0, q0, q1 and q2) -static WEBP_INLINE void DoFilter6(__m128i* const p2, __m128i* const p1, - __m128i* const p0, __m128i* const q0, - __m128i* const q1, __m128i* const q2, - const __m128i* const mask, int hev_thresh) { +static WEBP_INLINE void DoFilter6_SSE2(__m128i* const p2, __m128i* const p1, + __m128i* const p0, __m128i* const q0, + __m128i* const q1, __m128i* const q2, + const __m128i* const mask, + int hev_thresh) { const __m128i zero = _mm_setzero_si128(); const __m128i sign_bit = _mm_set1_epi8(0x80); __m128i a, not_hev; // compute hev mask - GetNotHEV(p1, p0, q0, q1, hev_thresh, ¬_hev); + GetNotHEV_SSE2(p1, p0, q0, q1, hev_thresh, ¬_hev); FLIP_SIGN_BIT4(*p1, *p0, *q0, *q1); FLIP_SIGN_BIT2(*p2, *q2); - GetBaseDelta(p1, p0, q0, q1, &a); + GetBaseDelta_SSE2(p1, p0, q0, q1, &a); { // do simple filter on pixels with hev const __m128i m = _mm_andnot_si128(not_hev, *mask); const __m128i f = _mm_and_si128(a, m); - DoSimpleFilter(p0, q0, &f); + DoSimpleFilter_SSE2(p0, q0, &f); } { // do strong filter on pixels with not hev @@ -460,15 +465,15 @@ static WEBP_INLINE void DoFilter6(__m128i* const p2, __m128i* const p1, const __m128i a0_lo = _mm_add_epi16(a1_lo, f9_lo); // Filter * 27 + 63 const __m128i a0_hi = _mm_add_epi16(a1_hi, f9_hi); // Filter * 27 + 63 - Update2Pixels(p2, q2, &a2_lo, &a2_hi); - Update2Pixels(p1, q1, &a1_lo, &a1_hi); - Update2Pixels(p0, q0, &a0_lo, &a0_hi); + Update2Pixels_SSE2(p2, q2, &a2_lo, &a2_hi); + Update2Pixels_SSE2(p1, q1, &a1_lo, &a1_hi); + Update2Pixels_SSE2(p0, q0, &a0_lo, &a0_hi); } } // reads 8 rows across a vertical edge. -static WEBP_INLINE void Load8x4(const uint8_t* const b, int stride, - __m128i* const p, __m128i* const q) { +static WEBP_INLINE void Load8x4_SSE2(const uint8_t* const b, int stride, + __m128i* const p, __m128i* const q) { // A0 = 63 62 61 60 23 22 21 20 43 42 41 40 03 02 01 00 // A1 = 73 72 71 70 33 32 31 30 53 52 51 50 13 12 11 10 const __m128i A0 = _mm_set_epi32( @@ -494,11 +499,11 @@ static WEBP_INLINE void Load8x4(const uint8_t* const b, int stride, *q = _mm_unpackhi_epi32(C0, C1); } -static WEBP_INLINE void Load16x4(const uint8_t* const r0, - const uint8_t* const r8, - int stride, - __m128i* const p1, __m128i* const p0, - __m128i* const q0, __m128i* const q1) { +static WEBP_INLINE void Load16x4_SSE2(const uint8_t* const r0, + const uint8_t* const r8, + int stride, + __m128i* const p1, __m128i* const p0, + __m128i* const q0, __m128i* const q1) { // Assume the pixels around the edge (|) are numbered as follows // 00 01 | 02 03 // 10 11 | 12 13 @@ -514,8 +519,8 @@ static WEBP_INLINE void Load16x4(const uint8_t* const r0, // q0 = 73 63 53 43 33 23 13 03 72 62 52 42 32 22 12 02 // p0 = f1 e1 d1 c1 b1 a1 91 81 f0 e0 d0 c0 b0 a0 90 80 // q1 = f3 e3 d3 c3 b3 a3 93 83 f2 e2 d2 c2 b2 a2 92 82 - Load8x4(r0, stride, p1, q0); - Load8x4(r8, stride, p0, q1); + Load8x4_SSE2(r0, stride, p1, q0); + Load8x4_SSE2(r8, stride, p0, q1); { // p1 = f0 e0 d0 c0 b0 a0 90 80 70 60 50 40 30 20 10 00 @@ -531,7 +536,8 @@ static WEBP_INLINE void Load16x4(const uint8_t* const r0, } } -static WEBP_INLINE void Store4x4(__m128i* const x, uint8_t* dst, int stride) { +static WEBP_INLINE void Store4x4_SSE2(__m128i* const x, + uint8_t* dst, int stride) { int i; for (i = 0; i < 4; ++i, dst += stride) { WebPUint32ToMem(dst, _mm_cvtsi128_si32(*x)); @@ -540,12 +546,12 @@ static WEBP_INLINE void Store4x4(__m128i* const x, uint8_t* dst, int stride) { } // Transpose back and store -static WEBP_INLINE void Store16x4(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - uint8_t* r0, uint8_t* r8, - int stride) { +static WEBP_INLINE void Store16x4_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + uint8_t* r0, uint8_t* r8, + int stride) { __m128i t1, p1_s, p0_s, q0_s, q1_s; // p0 = 71 70 61 60 51 50 41 40 31 30 21 20 11 10 01 00 @@ -572,55 +578,55 @@ static WEBP_INLINE void Store16x4(const __m128i* const p1, p1_s = _mm_unpacklo_epi16(t1, q1_s); q1_s = _mm_unpackhi_epi16(t1, q1_s); - Store4x4(&p0_s, r0, stride); + Store4x4_SSE2(&p0_s, r0, stride); r0 += 4 * stride; - Store4x4(&q0_s, r0, stride); + Store4x4_SSE2(&q0_s, r0, stride); - Store4x4(&p1_s, r8, stride); + Store4x4_SSE2(&p1_s, r8, stride); r8 += 4 * stride; - Store4x4(&q1_s, r8, stride); + Store4x4_SSE2(&q1_s, r8, stride); } //------------------------------------------------------------------------------ // Simple In-loop filtering (Paragraph 15.2) -static void SimpleVFilter16(uint8_t* p, int stride, int thresh) { +static void SimpleVFilter16_SSE2(uint8_t* p, int stride, int thresh) { // Load __m128i p1 = _mm_loadu_si128((__m128i*)&p[-2 * stride]); __m128i p0 = _mm_loadu_si128((__m128i*)&p[-stride]); __m128i q0 = _mm_loadu_si128((__m128i*)&p[0]); __m128i q1 = _mm_loadu_si128((__m128i*)&p[stride]); - DoFilter2(&p1, &p0, &q0, &q1, thresh); + DoFilter2_SSE2(&p1, &p0, &q0, &q1, thresh); // Store _mm_storeu_si128((__m128i*)&p[-stride], p0); _mm_storeu_si128((__m128i*)&p[0], q0); } -static void SimpleHFilter16(uint8_t* p, int stride, int thresh) { +static void SimpleHFilter16_SSE2(uint8_t* p, int stride, int thresh) { __m128i p1, p0, q0, q1; p -= 2; // beginning of p1 - Load16x4(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1); - DoFilter2(&p1, &p0, &q0, &q1, thresh); - Store16x4(&p1, &p0, &q0, &q1, p, p + 8 * stride, stride); + Load16x4_SSE2(p, p + 8 * stride, stride, &p1, &p0, &q0, &q1); + DoFilter2_SSE2(&p1, &p0, &q0, &q1, thresh); + Store16x4_SSE2(&p1, &p0, &q0, &q1, p, p + 8 * stride, stride); } -static void SimpleVFilter16i(uint8_t* p, int stride, int thresh) { +static void SimpleVFilter16i_SSE2(uint8_t* p, int stride, int thresh) { int k; for (k = 3; k > 0; --k) { p += 4 * stride; - SimpleVFilter16(p, stride, thresh); + SimpleVFilter16_SSE2(p, stride, thresh); } } -static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { +static void SimpleHFilter16i_SSE2(uint8_t* p, int stride, int thresh) { int k; for (k = 3; k > 0; --k) { p += 4; - SimpleHFilter16(p, stride, thresh); + SimpleHFilter16_SSE2(p, stride, thresh); } } @@ -628,60 +634,60 @@ static void SimpleHFilter16i(uint8_t* p, int stride, int thresh) { // Complex In-loop filtering (Paragraph 15.3) #define MAX_DIFF1(p3, p2, p1, p0, m) do { \ - m = MM_ABS(p1, p0); \ - m = _mm_max_epu8(m, MM_ABS(p3, p2)); \ - m = _mm_max_epu8(m, MM_ABS(p2, p1)); \ + (m) = MM_ABS(p1, p0); \ + (m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \ + (m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \ } while (0) #define MAX_DIFF2(p3, p2, p1, p0, m) do { \ - m = _mm_max_epu8(m, MM_ABS(p1, p0)); \ - m = _mm_max_epu8(m, MM_ABS(p3, p2)); \ - m = _mm_max_epu8(m, MM_ABS(p2, p1)); \ + (m) = _mm_max_epu8(m, MM_ABS(p1, p0)); \ + (m) = _mm_max_epu8(m, MM_ABS(p3, p2)); \ + (m) = _mm_max_epu8(m, MM_ABS(p2, p1)); \ } while (0) #define LOAD_H_EDGES4(p, stride, e1, e2, e3, e4) { \ - e1 = _mm_loadu_si128((__m128i*)&(p)[0 * stride]); \ - e2 = _mm_loadu_si128((__m128i*)&(p)[1 * stride]); \ - e3 = _mm_loadu_si128((__m128i*)&(p)[2 * stride]); \ - e4 = _mm_loadu_si128((__m128i*)&(p)[3 * stride]); \ + (e1) = _mm_loadu_si128((__m128i*)&(p)[0 * (stride)]); \ + (e2) = _mm_loadu_si128((__m128i*)&(p)[1 * (stride)]); \ + (e3) = _mm_loadu_si128((__m128i*)&(p)[2 * (stride)]); \ + (e4) = _mm_loadu_si128((__m128i*)&(p)[3 * (stride)]); \ } #define LOADUV_H_EDGE(p, u, v, stride) do { \ const __m128i U = _mm_loadl_epi64((__m128i*)&(u)[(stride)]); \ const __m128i V = _mm_loadl_epi64((__m128i*)&(v)[(stride)]); \ - p = _mm_unpacklo_epi64(U, V); \ + (p) = _mm_unpacklo_epi64(U, V); \ } while (0) #define LOADUV_H_EDGES4(u, v, stride, e1, e2, e3, e4) { \ - LOADUV_H_EDGE(e1, u, v, 0 * stride); \ - LOADUV_H_EDGE(e2, u, v, 1 * stride); \ - LOADUV_H_EDGE(e3, u, v, 2 * stride); \ - LOADUV_H_EDGE(e4, u, v, 3 * stride); \ + LOADUV_H_EDGE(e1, u, v, 0 * (stride)); \ + LOADUV_H_EDGE(e2, u, v, 1 * (stride)); \ + LOADUV_H_EDGE(e3, u, v, 2 * (stride)); \ + LOADUV_H_EDGE(e4, u, v, 3 * (stride)); \ } #define STOREUV(p, u, v, stride) { \ - _mm_storel_epi64((__m128i*)&u[(stride)], p); \ - p = _mm_srli_si128(p, 8); \ - _mm_storel_epi64((__m128i*)&v[(stride)], p); \ + _mm_storel_epi64((__m128i*)&(u)[(stride)], p); \ + (p) = _mm_srli_si128(p, 8); \ + _mm_storel_epi64((__m128i*)&(v)[(stride)], p); \ } -static WEBP_INLINE void ComplexMask(const __m128i* const p1, - const __m128i* const p0, - const __m128i* const q0, - const __m128i* const q1, - int thresh, int ithresh, - __m128i* const mask) { +static WEBP_INLINE void ComplexMask_SSE2(const __m128i* const p1, + const __m128i* const p0, + const __m128i* const q0, + const __m128i* const q1, + int thresh, int ithresh, + __m128i* const mask) { const __m128i it = _mm_set1_epi8(ithresh); const __m128i diff = _mm_subs_epu8(*mask, it); const __m128i thresh_mask = _mm_cmpeq_epi8(diff, _mm_setzero_si128()); __m128i filter_mask; - NeedsFilter(p1, p0, q0, q1, thresh, &filter_mask); + NeedsFilter_SSE2(p1, p0, q0, q1, thresh, &filter_mask); *mask = _mm_and_si128(thresh_mask, filter_mask); } // on macroblock edges -static void VFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { +static void VFilter16_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { __m128i t1; __m128i mask; __m128i p2, p1, p0, q0, q1, q2; @@ -694,8 +700,8 @@ static void VFilter16(uint8_t* p, int stride, LOAD_H_EDGES4(p, stride, q0, q1, q2, t1); MAX_DIFF2(t1, q2, q1, q0, mask); - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); // Store _mm_storeu_si128((__m128i*)&p[-3 * stride], p2); @@ -706,28 +712,28 @@ static void VFilter16(uint8_t* p, int stride, _mm_storeu_si128((__m128i*)&p[+2 * stride], q2); } -static void HFilter16(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { +static void HFilter16_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { __m128i mask; __m128i p3, p2, p1, p0, q0, q1, q2, q3; uint8_t* const b = p - 4; - Load16x4(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0 + Load16x4_SSE2(b, b + 8 * stride, stride, &p3, &p2, &p1, &p0); MAX_DIFF1(p3, p2, p1, p0, mask); - Load16x4(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3 + Load16x4_SSE2(p, p + 8 * stride, stride, &q0, &q1, &q2, &q3); MAX_DIFF2(q3, q2, q1, q0, mask); - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); - Store16x4(&p3, &p2, &p1, &p0, b, b + 8 * stride, stride); - Store16x4(&q0, &q1, &q2, &q3, p, p + 8 * stride, stride); + Store16x4_SSE2(&p3, &p2, &p1, &p0, b, b + 8 * stride, stride); + Store16x4_SSE2(&q0, &q1, &q2, &q3, p, p + 8 * stride, stride); } // on three inner edges -static void VFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { +static void VFilter16i_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { int k; __m128i p3, p2, p1, p0; // loop invariants @@ -744,8 +750,8 @@ static void VFilter16i(uint8_t* p, int stride, // p3 and p2 are not just temporary variables here: they will be // re-used for next span. And q2/q3 will become p1/p0 accordingly. - ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh); + ComplexMask_SSE2(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &p3, &p2, &mask, hev_thresh); // Store _mm_storeu_si128((__m128i*)&b[0 * stride], p1); @@ -759,12 +765,12 @@ static void VFilter16i(uint8_t* p, int stride, } } -static void HFilter16i(uint8_t* p, int stride, - int thresh, int ithresh, int hev_thresh) { +static void HFilter16i_SSE2(uint8_t* p, int stride, + int thresh, int ithresh, int hev_thresh) { int k; __m128i p3, p2, p1, p0; // loop invariants - Load16x4(p, p + 8 * stride, stride, &p3, &p2, &p1, &p0); // prologue + Load16x4_SSE2(p, p + 8 * stride, stride, &p3, &p2, &p1, &p0); // prologue for (k = 3; k > 0; --k) { __m128i mask, tmp1, tmp2; @@ -773,13 +779,13 @@ static void HFilter16i(uint8_t* p, int stride, p += 4; // beginning of q0 (and next span) MAX_DIFF1(p3, p2, p1, p0, mask); // compute partial mask - Load16x4(p, p + 8 * stride, stride, &p3, &p2, &tmp1, &tmp2); + Load16x4_SSE2(p, p + 8 * stride, stride, &p3, &p2, &tmp1, &tmp2); MAX_DIFF2(p3, p2, tmp1, tmp2, mask); - ComplexMask(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &p3, &p2, &mask, hev_thresh); + ComplexMask_SSE2(&p1, &p0, &p3, &p2, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &p3, &p2, &mask, hev_thresh); - Store16x4(&p1, &p0, &p3, &p2, b, b + 8 * stride, stride); + Store16x4_SSE2(&p1, &p0, &p3, &p2, b, b + 8 * stride, stride); // rotate samples p1 = tmp1; @@ -788,8 +794,8 @@ static void HFilter16i(uint8_t* p, int stride, } // 8-pixels wide variant, for chroma filtering -static void VFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { +static void VFilter8_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { __m128i mask; __m128i t1, p2, p1, p0, q0, q1, q2; @@ -801,8 +807,8 @@ static void VFilter8(uint8_t* u, uint8_t* v, int stride, LOADUV_H_EDGES4(u, v, stride, q0, q1, q2, t1); MAX_DIFF2(t1, q2, q1, q0, mask); - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); // Store STOREUV(p2, u, v, -3 * stride); @@ -813,28 +819,28 @@ static void VFilter8(uint8_t* u, uint8_t* v, int stride, STOREUV(q2, u, v, 2 * stride); } -static void HFilter8(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { +static void HFilter8_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { __m128i mask; __m128i p3, p2, p1, p0, q0, q1, q2, q3; uint8_t* const tu = u - 4; uint8_t* const tv = v - 4; - Load16x4(tu, tv, stride, &p3, &p2, &p1, &p0); // p3, p2, p1, p0 + Load16x4_SSE2(tu, tv, stride, &p3, &p2, &p1, &p0); MAX_DIFF1(p3, p2, p1, p0, mask); - Load16x4(u, v, stride, &q0, &q1, &q2, &q3); // q0, q1, q2, q3 + Load16x4_SSE2(u, v, stride, &q0, &q1, &q2, &q3); MAX_DIFF2(q3, q2, q1, q0, mask); - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter6(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter6_SSE2(&p2, &p1, &p0, &q0, &q1, &q2, &mask, hev_thresh); - Store16x4(&p3, &p2, &p1, &p0, tu, tv, stride); - Store16x4(&q0, &q1, &q2, &q3, u, v, stride); + Store16x4_SSE2(&p3, &p2, &p1, &p0, tu, tv, stride); + Store16x4_SSE2(&q0, &q1, &q2, &q3, u, v, stride); } -static void VFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { +static void VFilter8i_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { __m128i mask; __m128i t1, t2, p1, p0, q0, q1; @@ -849,8 +855,8 @@ static void VFilter8i(uint8_t* u, uint8_t* v, int stride, LOADUV_H_EDGES4(u, v, stride, q0, q1, t1, t2); MAX_DIFF2(t2, t1, q1, q0, mask); - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh); + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &q0, &q1, &mask, hev_thresh); // Store STOREUV(p1, u, v, -2 * stride); @@ -859,24 +865,24 @@ static void VFilter8i(uint8_t* u, uint8_t* v, int stride, STOREUV(q1, u, v, 1 * stride); } -static void HFilter8i(uint8_t* u, uint8_t* v, int stride, - int thresh, int ithresh, int hev_thresh) { +static void HFilter8i_SSE2(uint8_t* u, uint8_t* v, int stride, + int thresh, int ithresh, int hev_thresh) { __m128i mask; __m128i t1, t2, p1, p0, q0, q1; - Load16x4(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0 + Load16x4_SSE2(u, v, stride, &t2, &t1, &p1, &p0); // p3, p2, p1, p0 MAX_DIFF1(t2, t1, p1, p0, mask); u += 4; // beginning of q0 v += 4; - Load16x4(u, v, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3 + Load16x4_SSE2(u, v, stride, &q0, &q1, &t1, &t2); // q0, q1, q2, q3 MAX_DIFF2(t2, t1, q1, q0, mask); - ComplexMask(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); - DoFilter4(&p1, &p0, &q0, &q1, &mask, hev_thresh); + ComplexMask_SSE2(&p1, &p0, &q0, &q1, thresh, ithresh, &mask); + DoFilter4_SSE2(&p1, &p0, &q0, &q1, &mask, hev_thresh); u -= 2; // beginning of p1 v -= 2; - Store16x4(&p1, &p0, &q0, &q1, u, v, stride); + Store16x4_SSE2(&p1, &p0, &q0, &q1, u, v, stride); } //------------------------------------------------------------------------------ @@ -893,7 +899,7 @@ static void HFilter8i(uint8_t* u, uint8_t* v, int stride, // where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1 // and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1 -static void VE4(uint8_t* dst) { // vertical +static void VE4_SSE2(uint8_t* dst) { // vertical const __m128i one = _mm_set1_epi8(1); const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); @@ -909,7 +915,7 @@ static void VE4(uint8_t* dst) { // vertical } } -static void LD4(uint8_t* dst) { // Down-Left +static void LD4_SSE2(uint8_t* dst) { // Down-Left const __m128i one = _mm_set1_epi8(1); const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS)); const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); @@ -925,7 +931,7 @@ static void LD4(uint8_t* dst) { // Down-Left WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); } -static void VR4(uint8_t* dst) { // Vertical-Right +static void VR4_SSE2(uint8_t* dst) { // Vertical-Right const __m128i one = _mm_set1_epi8(1); const int I = dst[-1 + 0 * BPS]; const int J = dst[-1 + 1 * BPS]; @@ -950,7 +956,7 @@ static void VR4(uint8_t* dst) { // Vertical-Right DST(0, 3) = AVG3(K, J, I); } -static void VL4(uint8_t* dst) { // Vertical-Left +static void VL4_SSE2(uint8_t* dst) { // Vertical-Left const __m128i one = _mm_set1_epi8(1); const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(dst - BPS)); const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1); @@ -975,7 +981,7 @@ static void VL4(uint8_t* dst) { // Vertical-Left DST(3, 3) = (extra_out >> 8) & 0xff; } -static void RD4(uint8_t* dst) { // Down-right +static void RD4_SSE2(uint8_t* dst) { // Down-right const __m128i one = _mm_set1_epi8(1); const __m128i XABCD = _mm_loadl_epi64((__m128i*)(dst - BPS - 1)); const __m128i ____XABCD = _mm_slli_si128(XABCD, 4); @@ -1004,7 +1010,7 @@ static void RD4(uint8_t* dst) { // Down-right //------------------------------------------------------------------------------ // Luma 16x16 -static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { +static WEBP_INLINE void TrueMotion_SSE2(uint8_t* dst, int size) { const uint8_t* top = dst - BPS; const __m128i zero = _mm_setzero_si128(); int y; @@ -1041,11 +1047,11 @@ static WEBP_INLINE void TrueMotion(uint8_t* dst, int size) { } } -static void TM4(uint8_t* dst) { TrueMotion(dst, 4); } -static void TM8uv(uint8_t* dst) { TrueMotion(dst, 8); } -static void TM16(uint8_t* dst) { TrueMotion(dst, 16); } +static void TM4_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 4); } +static void TM8uv_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 8); } +static void TM16_SSE2(uint8_t* dst) { TrueMotion_SSE2(dst, 16); } -static void VE16(uint8_t* dst) { +static void VE16_SSE2(uint8_t* dst) { const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); int j; for (j = 0; j < 16; ++j) { @@ -1053,7 +1059,7 @@ static void VE16(uint8_t* dst) { } } -static void HE16(uint8_t* dst) { // horizontal +static void HE16_SSE2(uint8_t* dst) { // horizontal int j; for (j = 16; j > 0; --j) { const __m128i values = _mm_set1_epi8(dst[-1]); @@ -1062,7 +1068,7 @@ static void HE16(uint8_t* dst) { // horizontal } } -static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) { +static WEBP_INLINE void Put16_SSE2(uint8_t v, uint8_t* dst) { int j; const __m128i values = _mm_set1_epi8(v); for (j = 0; j < 16; ++j) { @@ -1070,7 +1076,7 @@ static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) { } } -static void DC16(uint8_t* dst) { // DC +static void DC16_SSE2(uint8_t* dst) { // DC const __m128i zero = _mm_setzero_si128(); const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); const __m128i sad8x2 = _mm_sad_epu8(top, zero); @@ -1083,37 +1089,37 @@ static void DC16(uint8_t* dst) { // DC } { const int DC = _mm_cvtsi128_si32(sum) + left + 16; - Put16(DC >> 5, dst); + Put16_SSE2(DC >> 5, dst); } } -static void DC16NoTop(uint8_t* dst) { // DC with top samples not available +static void DC16NoTop_SSE2(uint8_t* dst) { // DC with top samples unavailable int DC = 8; int j; for (j = 0; j < 16; ++j) { DC += dst[-1 + j * BPS]; } - Put16(DC >> 4, dst); + Put16_SSE2(DC >> 4, dst); } -static void DC16NoLeft(uint8_t* dst) { // DC with left samples not available +static void DC16NoLeft_SSE2(uint8_t* dst) { // DC with left samples unavailable const __m128i zero = _mm_setzero_si128(); const __m128i top = _mm_loadu_si128((const __m128i*)(dst - BPS)); const __m128i sad8x2 = _mm_sad_epu8(top, zero); // sum the two sads: sad8x2[0:1] + sad8x2[8:9] const __m128i sum = _mm_add_epi16(sad8x2, _mm_shuffle_epi32(sad8x2, 2)); const int DC = _mm_cvtsi128_si32(sum) + 8; - Put16(DC >> 4, dst); + Put16_SSE2(DC >> 4, dst); } -static void DC16NoTopLeft(uint8_t* dst) { // DC with no top and left samples - Put16(0x80, dst); +static void DC16NoTopLeft_SSE2(uint8_t* dst) { // DC with no top & left samples + Put16_SSE2(0x80, dst); } //------------------------------------------------------------------------------ // Chroma -static void VE8uv(uint8_t* dst) { // vertical +static void VE8uv_SSE2(uint8_t* dst) { // vertical int j; const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); for (j = 0; j < 8; ++j) { @@ -1121,17 +1127,8 @@ static void VE8uv(uint8_t* dst) { // vertical } } -static void HE8uv(uint8_t* dst) { // horizontal - int j; - for (j = 0; j < 8; ++j) { - const __m128i values = _mm_set1_epi8(dst[-1]); - _mm_storel_epi64((__m128i*)dst, values); - dst += BPS; - } -} - // helper for chroma-DC predictions -static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) { +static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) { int j; const __m128i values = _mm_set1_epi8(v); for (j = 0; j < 8; ++j) { @@ -1139,7 +1136,7 @@ static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) { } } -static void DC8uv(uint8_t* dst) { // DC +static void DC8uv_SSE2(uint8_t* dst) { // DC const __m128i zero = _mm_setzero_si128(); const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); const __m128i sum = _mm_sad_epu8(top, zero); @@ -1150,29 +1147,29 @@ static void DC8uv(uint8_t* dst) { // DC } { const int DC = _mm_cvtsi128_si32(sum) + left + 8; - Put8x8uv(DC >> 4, dst); + Put8x8uv_SSE2(DC >> 4, dst); } } -static void DC8uvNoLeft(uint8_t* dst) { // DC with no left samples +static void DC8uvNoLeft_SSE2(uint8_t* dst) { // DC with no left samples const __m128i zero = _mm_setzero_si128(); const __m128i top = _mm_loadl_epi64((const __m128i*)(dst - BPS)); const __m128i sum = _mm_sad_epu8(top, zero); const int DC = _mm_cvtsi128_si32(sum) + 4; - Put8x8uv(DC >> 3, dst); + Put8x8uv_SSE2(DC >> 3, dst); } -static void DC8uvNoTop(uint8_t* dst) { // DC with no top samples +static void DC8uvNoTop_SSE2(uint8_t* dst) { // DC with no top samples int dc0 = 4; int i; for (i = 0; i < 8; ++i) { dc0 += dst[-1 + i * BPS]; } - Put8x8uv(dc0 >> 3, dst); + Put8x8uv_SSE2(dc0 >> 3, dst); } -static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing - Put8x8uv(0x80, dst); +static void DC8uvNoTopLeft_SSE2(uint8_t* dst) { // DC with nothing + Put8x8uv_SSE2(0x80, dst); } //------------------------------------------------------------------------------ @@ -1181,47 +1178,46 @@ static void DC8uvNoTopLeft(uint8_t* dst) { // DC with nothing extern void VP8DspInitSSE2(void); WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE2(void) { - VP8Transform = Transform; -#if defined(USE_TRANSFORM_AC3) - VP8TransformAC3 = TransformAC3; + VP8Transform = Transform_SSE2; +#if (USE_TRANSFORM_AC3 == 1) + VP8TransformAC3 = TransformAC3_SSE2; #endif - VP8VFilter16 = VFilter16; - VP8HFilter16 = HFilter16; - VP8VFilter8 = VFilter8; - VP8HFilter8 = HFilter8; - VP8VFilter16i = VFilter16i; - VP8HFilter16i = HFilter16i; - VP8VFilter8i = VFilter8i; - VP8HFilter8i = HFilter8i; + VP8VFilter16 = VFilter16_SSE2; + VP8HFilter16 = HFilter16_SSE2; + VP8VFilter8 = VFilter8_SSE2; + VP8HFilter8 = HFilter8_SSE2; + VP8VFilter16i = VFilter16i_SSE2; + VP8HFilter16i = HFilter16i_SSE2; + VP8VFilter8i = VFilter8i_SSE2; + VP8HFilter8i = HFilter8i_SSE2; - VP8SimpleVFilter16 = SimpleVFilter16; - VP8SimpleHFilter16 = SimpleHFilter16; - VP8SimpleVFilter16i = SimpleVFilter16i; - VP8SimpleHFilter16i = SimpleHFilter16i; + VP8SimpleVFilter16 = SimpleVFilter16_SSE2; + VP8SimpleHFilter16 = SimpleHFilter16_SSE2; + VP8SimpleVFilter16i = SimpleVFilter16i_SSE2; + VP8SimpleHFilter16i = SimpleHFilter16i_SSE2; - VP8PredLuma4[1] = TM4; - VP8PredLuma4[2] = VE4; - VP8PredLuma4[4] = RD4; - VP8PredLuma4[5] = VR4; - VP8PredLuma4[6] = LD4; - VP8PredLuma4[7] = VL4; + VP8PredLuma4[1] = TM4_SSE2; + VP8PredLuma4[2] = VE4_SSE2; + VP8PredLuma4[4] = RD4_SSE2; + VP8PredLuma4[5] = VR4_SSE2; + VP8PredLuma4[6] = LD4_SSE2; + VP8PredLuma4[7] = VL4_SSE2; - VP8PredLuma16[0] = DC16; - VP8PredLuma16[1] = TM16; - VP8PredLuma16[2] = VE16; - VP8PredLuma16[3] = HE16; - VP8PredLuma16[4] = DC16NoTop; - VP8PredLuma16[5] = DC16NoLeft; - VP8PredLuma16[6] = DC16NoTopLeft; + VP8PredLuma16[0] = DC16_SSE2; + VP8PredLuma16[1] = TM16_SSE2; + VP8PredLuma16[2] = VE16_SSE2; + VP8PredLuma16[3] = HE16_SSE2; + VP8PredLuma16[4] = DC16NoTop_SSE2; + VP8PredLuma16[5] = DC16NoLeft_SSE2; + VP8PredLuma16[6] = DC16NoTopLeft_SSE2; - VP8PredChroma8[0] = DC8uv; - VP8PredChroma8[1] = TM8uv; - VP8PredChroma8[2] = VE8uv; - VP8PredChroma8[3] = HE8uv; - VP8PredChroma8[4] = DC8uvNoTop; - VP8PredChroma8[5] = DC8uvNoLeft; - VP8PredChroma8[6] = DC8uvNoTopLeft; + VP8PredChroma8[0] = DC8uv_SSE2; + VP8PredChroma8[1] = TM8uv_SSE2; + VP8PredChroma8[2] = VE8uv_SSE2; + VP8PredChroma8[4] = DC8uvNoTop_SSE2; + VP8PredChroma8[5] = DC8uvNoLeft_SSE2; + VP8PredChroma8[6] = DC8uvNoTopLeft_SSE2; } #else // !WEBP_USE_SSE2 diff --git a/3rdparty/libwebp/dsp/dec_sse41.c b/3rdparty/libwebp/src/dsp/dec_sse41.c similarity index 87% rename from 3rdparty/libwebp/dsp/dec_sse41.c rename to 3rdparty/libwebp/src/dsp/dec_sse41.c index 4e81ec4d80..8f18506d54 100644 --- a/3rdparty/libwebp/dsp/dec_sse41.c +++ b/3rdparty/libwebp/src/dsp/dec_sse41.c @@ -11,15 +11,15 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE41) #include -#include "../dec/vp8i_dec.h" -#include "../utils/utils.h" +#include "src/dec/vp8i_dec.h" +#include "src/utils/utils.h" -static void HE16(uint8_t* dst) { // horizontal +static void HE16_SSE41(uint8_t* dst) { // horizontal int j; const __m128i kShuffle3 = _mm_set1_epi8(3); for (j = 16; j > 0; --j) { @@ -36,7 +36,7 @@ static void HE16(uint8_t* dst) { // horizontal extern void VP8DspInitSSE41(void); WEBP_TSAN_IGNORE_FUNCTION void VP8DspInitSSE41(void) { - VP8PredLuma16[3] = HE16; + VP8PredLuma16[3] = HE16_SSE41; } #else // !WEBP_USE_SSE41 diff --git a/3rdparty/libwebp/dsp/dsp.h b/3rdparty/libwebp/src/dsp/dsp.h similarity index 90% rename from 3rdparty/libwebp/dsp/dsp.h rename to 3rdparty/libwebp/src/dsp/dsp.h index 813fed4a35..99eefe092f 100644 --- a/3rdparty/libwebp/dsp/dsp.h +++ b/3rdparty/libwebp/src/dsp/dsp.h @@ -15,10 +15,10 @@ #define WEBP_DSP_DSP_H_ #ifdef HAVE_CONFIG_H -#include "../webp/config.h" +#include "src/webp/config.h" #endif -#include "../webp/types.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -38,10 +38,22 @@ extern "C" { # define LOCAL_GCC_PREREQ(maj, min) 0 #endif +#if defined(__clang__) +# define LOCAL_CLANG_VERSION ((__clang_major__ << 8) | __clang_minor__) +# define LOCAL_CLANG_PREREQ(maj, min) \ + (LOCAL_CLANG_VERSION >= (((maj) << 8) | (min))) +#else +# define LOCAL_CLANG_VERSION 0 +# define LOCAL_CLANG_PREREQ(maj, min) 0 +#endif + #ifndef __has_builtin # define __has_builtin(x) 0 #endif +// for now, none of the optimizations below are available in emscripten +#if !defined(EMSCRIPTEN) + #if defined(_MSC_VER) && _MSC_VER > 1310 && \ (defined(_M_X64) || defined(_M_IX86)) #define WEBP_MSC_SSE2 // Visual C++ SSE2 targets @@ -68,18 +80,20 @@ extern "C" { #define WEBP_USE_AVX2 #endif -#if defined(__ANDROID__) && defined(__ARM_ARCH_7A__) -#define WEBP_ANDROID_NEON // Android targets that might support NEON -#endif - // The intrinsics currently cause compiler errors with arm-nacl-gcc and the // inline assembly would need to be modified for use with Native Client. -#if (defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON) || \ +#if (defined(__ARM_NEON__) || \ defined(__aarch64__) || defined(WEBP_HAVE_NEON)) && \ !defined(__native_client__) #define WEBP_USE_NEON #endif +#if !defined(WEBP_USE_NEON) && defined(__ANDROID__) && \ + defined(__ARM_ARCH_7A__) && defined(HAVE_CPU_FEATURES_H) +#define WEBP_ANDROID_NEON // Android targets that may have NEON +#define WEBP_USE_NEON +#endif + #if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_M_ARM) #define WEBP_USE_NEON #define WEBP_USE_INTRINSICS @@ -90,7 +104,7 @@ extern "C" { #define WEBP_USE_MIPS32 #if (__mips_isa_rev >= 2) #define WEBP_USE_MIPS32_R2 -#if defined(__mips_dspr2) || (__mips_dsp_rev >= 2) +#if defined(__mips_dspr2) || (defined(__mips_dsp_rev) && __mips_dsp_rev >= 2) #define WEBP_USE_MIPS_DSP_R2 #endif #endif @@ -100,6 +114,24 @@ extern "C" { #define WEBP_USE_MSA #endif +#endif /* EMSCRIPTEN */ + +#ifndef WEBP_DSP_OMIT_C_CODE +#define WEBP_DSP_OMIT_C_CODE 1 +#endif + +#if (defined(__aarch64__) || defined(__ARM_NEON__)) && WEBP_DSP_OMIT_C_CODE +#define WEBP_NEON_OMIT_C_CODE 1 +#else +#define WEBP_NEON_OMIT_C_CODE 0 +#endif + +#if !(LOCAL_CLANG_PREREQ(3,8) || LOCAL_GCC_PREREQ(4,8) || defined(__aarch64__)) +#define WEBP_NEON_WORK_AROUND_GCC 1 +#else +#define WEBP_NEON_WORK_AROUND_GCC 0 +#endif + // This macro prevents thread_sanitizer from reporting known concurrent writes. #define WEBP_TSAN_IGNORE_FUNCTION #if defined(__has_feature) @@ -129,6 +161,11 @@ extern "C" { #endif #endif +// Regularize the definition of WEBP_SWAP_16BIT_CSP (backward compatibility) +#if !defined(WEBP_SWAP_16BIT_CSP) +#define WEBP_SWAP_16BIT_CSP 0 +#endif + typedef enum { kSSE2, kSSE3, @@ -143,7 +180,7 @@ typedef enum { } CPUFeature; // returns true if the CPU supports the feature. typedef int (*VP8CPUInfo)(CPUFeature feature); -WEBP_EXTERN(VP8CPUInfo) VP8GetCPUInfo; +WEBP_EXTERN VP8CPUInfo VP8GetCPUInfo; //------------------------------------------------------------------------------ // Init stub generator @@ -271,6 +308,7 @@ typedef double (*VP8SSIMGetClippedFunc)(const uint8_t* src1, int stride1, int xo, int yo, // center position int W, int H); // plane dimension +#if !defined(WEBP_REDUCE_SIZE) // This version is called with the guarantee that you can load 8 bytes and // 8 rows at offset src1 and src2 typedef double (*VP8SSIMGetFunc)(const uint8_t* src1, int stride1, @@ -278,10 +316,13 @@ typedef double (*VP8SSIMGetFunc)(const uint8_t* src1, int stride1, extern VP8SSIMGetFunc VP8SSIMGet; // unclipped / unchecked extern VP8SSIMGetClippedFunc VP8SSIMGetClipped; // with clipping +#endif +#if !defined(WEBP_DISABLE_STATS) typedef uint32_t (*VP8AccumulateSSEFunc)(const uint8_t* src1, const uint8_t* src2, int len); extern VP8AccumulateSSEFunc VP8AccumulateSSE; +#endif // must be called before using any of the above directly void VP8SSIMDspInit(void); @@ -462,12 +503,12 @@ extern WebPRescalerExportRowFunc WebPRescalerExportRowExpand; extern WebPRescalerExportRowFunc WebPRescalerExportRowShrink; // Plain-C implementation, as fall-back. -extern void WebPRescalerImportRowExpandC(struct WebPRescaler* const wrk, - const uint8_t* src); -extern void WebPRescalerImportRowShrinkC(struct WebPRescaler* const wrk, - const uint8_t* src); -extern void WebPRescalerExportRowExpandC(struct WebPRescaler* const wrk); -extern void WebPRescalerExportRowShrinkC(struct WebPRescaler* const wrk); +extern void WebPRescalerImportRowExpand_C(struct WebPRescaler* const wrk, + const uint8_t* src); +extern void WebPRescalerImportRowShrink_C(struct WebPRescaler* const wrk, + const uint8_t* src); +extern void WebPRescalerExportRowExpand_C(struct WebPRescaler* const wrk); +extern void WebPRescalerExportRowShrink_C(struct WebPRescaler* const wrk); // Main entry calls: extern void WebPRescalerImportRow(struct WebPRescaler* const wrk, @@ -533,25 +574,22 @@ void WebPMultRows(uint8_t* ptr, int stride, int width, int num_rows, int inverse); // Plain-C versions, used as fallback by some implementations. -void WebPMultRowC(uint8_t* const ptr, const uint8_t* const alpha, - int width, int inverse); -void WebPMultARGBRowC(uint32_t* const ptr, int width, int inverse); +void WebPMultRow_C(uint8_t* const ptr, const uint8_t* const alpha, + int width, int inverse); +void WebPMultARGBRow_C(uint32_t* const ptr, int width, int inverse); + +// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order. +extern void (*WebPPackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b, + int len, int step, uint32_t* out); + +// This function returns true if src[i] contains a value different from 0xff. +extern int (*WebPHasAlpha8b)(const uint8_t* src, int length); +// This function returns true if src[4*i] contains a value different from 0xff. +extern int (*WebPHasAlpha32b)(const uint8_t* src, int length); // To be called first before using the above. void WebPInitAlphaProcessing(void); -// ARGB packing function: a/r/g/b input is rgba or bgra order. -extern void (*VP8PackARGB)(const uint8_t* a, const uint8_t* r, - const uint8_t* g, const uint8_t* b, int len, - uint32_t* out); - -// RGB packing function. 'step' can be 3 or 4. r/g/b input is rgb or bgr order. -extern void (*VP8PackRGB)(const uint8_t* r, const uint8_t* g, const uint8_t* b, - int len, int step, uint32_t* out); - -// To be called first before using the above. -void VP8EncDspARGBInit(void); - //------------------------------------------------------------------------------ // Filter functions diff --git a/3rdparty/libwebp/dsp/enc.c b/3rdparty/libwebp/src/dsp/enc.c similarity index 75% rename from 3rdparty/libwebp/dsp/enc.c rename to 3rdparty/libwebp/src/dsp/enc.c index f31bc6de18..1c807f1df7 100644 --- a/3rdparty/libwebp/dsp/enc.c +++ b/3rdparty/libwebp/src/dsp/enc.c @@ -14,16 +14,18 @@ #include #include // for abs() -#include "./dsp.h" -#include "../enc/vp8i_enc.h" +#include "src/dsp/dsp.h" +#include "src/enc/vp8i_enc.h" static WEBP_INLINE uint8_t clip_8b(int v) { return (!(v & ~0xff)) ? v : (v < 0) ? 0 : 255; } +#if !WEBP_NEON_OMIT_C_CODE static WEBP_INLINE int clip_max(int v, int max) { return (v > max) ? max : v; } +#endif // !WEBP_NEON_OMIT_C_CODE //------------------------------------------------------------------------------ // Compute susceptibility based on DCT-coeff histograms: @@ -56,9 +58,10 @@ void VP8SetHistogramData(const int distribution[MAX_COEFF_THRESH + 1], histo->last_non_zero = last_non_zero; } -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { +#if !WEBP_NEON_OMIT_C_CODE +static void CollectHistogram_C(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { int j; int distribution[MAX_COEFF_THRESH + 1] = { 0 }; for (j = start_block; j < end_block; ++j) { @@ -76,6 +79,7 @@ static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, } VP8SetHistogramData(distribution, histo); } +#endif // !WEBP_NEON_OMIT_C_CODE //------------------------------------------------------------------------------ // run-time tables (~4k) @@ -100,6 +104,8 @@ static WEBP_TSAN_IGNORE_FUNCTION void InitTables(void) { //------------------------------------------------------------------------------ // Transforms (Paragraph 14.4) +#if !WEBP_NEON_OMIT_C_CODE + #define STORE(x, y, v) \ dst[(x) + (y) * BPS] = clip_8b(ref[(x) + (y) * BPS] + ((v) >> 3)) @@ -140,15 +146,15 @@ static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, } } -static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two) { +static void ITransform_C(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two) { ITransformOne(ref, in, dst); if (do_two) { ITransformOne(ref + 4, in + 16, dst + 4); } } -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { +static void FTransform_C(const uint8_t* src, const uint8_t* ref, int16_t* out) { int i; int tmp[16]; for (i = 0; i < 4; ++i, src += BPS, ref += BPS) { @@ -176,13 +182,16 @@ static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { out[12+ i] = ((a3 * 2217 - a2 * 5352 + 51000) >> 16); } } +#endif // !WEBP_NEON_OMIT_C_CODE -static void FTransform2(const uint8_t* src, const uint8_t* ref, int16_t* out) { +static void FTransform2_C(const uint8_t* src, const uint8_t* ref, + int16_t* out) { VP8FTransform(src, ref, out); VP8FTransform(src + 4, ref + 4, out + 16); } -static void FTransformWHT(const int16_t* in, int16_t* out) { +#if !WEBP_NEON_OMIT_C_CODE +static void FTransformWHT_C(const int16_t* in, int16_t* out) { // input is 12b signed int32_t tmp[16]; int i; @@ -211,6 +220,7 @@ static void FTransformWHT(const int16_t* in, int16_t* out) { out[12 + i] = b3 >> 1; } } +#endif // !WEBP_NEON_OMIT_C_CODE #undef MUL #undef STORE @@ -303,8 +313,8 @@ static WEBP_INLINE void DCMode(uint8_t* dst, const uint8_t* left, //------------------------------------------------------------------------------ // Chroma 8x8 prediction (paragraph 12.2) -static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { +static void IntraChromaPreds_C(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { // U block DCMode(C8DC8 + dst, left, top, 8, 8, 4); VerticalPred(C8VE8 + dst, top, 8); @@ -323,8 +333,8 @@ static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, //------------------------------------------------------------------------------ // luma 16x16 prediction (paragraph 12.3) -static void Intra16Preds(uint8_t* dst, - const uint8_t* left, const uint8_t* top) { +static void Intra16Preds_C(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { DCMode(I16DC16 + dst, left, top, 16, 16, 5); VerticalPred(I16VE16 + dst, top, 16); HorizontalPred(I16HE16 + dst, left, 16); @@ -507,7 +517,7 @@ static void TM4(uint8_t* dst, const uint8_t* top) { // Left samples are top[-5 .. -2], top_left is top[-1], top are // located at top[0..3], and top right is top[4..7] -static void Intra4Preds(uint8_t* dst, const uint8_t* top) { +static void Intra4Preds_C(uint8_t* dst, const uint8_t* top) { DC4(I4DC4 + dst, top); TM4(I4TM4 + dst, top); VE4(I4VE4 + dst, top); @@ -523,6 +533,7 @@ static void Intra4Preds(uint8_t* dst, const uint8_t* top) { //------------------------------------------------------------------------------ // Metric +#if !WEBP_NEON_OMIT_C_CODE static WEBP_INLINE int GetSSE(const uint8_t* a, const uint8_t* b, int w, int h) { int count = 0; @@ -538,20 +549,21 @@ static WEBP_INLINE int GetSSE(const uint8_t* a, const uint8_t* b, return count; } -static int SSE16x16(const uint8_t* a, const uint8_t* b) { +static int SSE16x16_C(const uint8_t* a, const uint8_t* b) { return GetSSE(a, b, 16, 16); } -static int SSE16x8(const uint8_t* a, const uint8_t* b) { +static int SSE16x8_C(const uint8_t* a, const uint8_t* b) { return GetSSE(a, b, 16, 8); } -static int SSE8x8(const uint8_t* a, const uint8_t* b) { +static int SSE8x8_C(const uint8_t* a, const uint8_t* b) { return GetSSE(a, b, 8, 8); } -static int SSE4x4(const uint8_t* a, const uint8_t* b) { +static int SSE4x4_C(const uint8_t* a, const uint8_t* b) { return GetSSE(a, b, 4, 4); } +#endif // !WEBP_NEON_OMIT_C_CODE -static void Mean16x4(const uint8_t* ref, uint32_t dc[4]) { +static void Mean16x4_C(const uint8_t* ref, uint32_t dc[4]) { int k, x, y; for (k = 0; k < 4; ++k) { uint32_t avg = 0; @@ -571,6 +583,7 @@ static void Mean16x4(const uint8_t* ref, uint32_t dc[4]) { // We try to match the spectral content (weighted) between source and // reconstructed samples. +#if !WEBP_NEON_OMIT_C_CODE // Hadamard transform // Returns the weighted sum of the absolute value of transformed coefficients. // w[] contains a row-major 4 by 4 symmetric matrix. @@ -608,24 +621,25 @@ static int TTransform(const uint8_t* in, const uint16_t* w) { return sum; } -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { +static int Disto4x4_C(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { const int sum1 = TTransform(a, w); const int sum2 = TTransform(b, w); return abs(sum2 - sum1) >> 5; } -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { +static int Disto16x16_C(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { int D = 0; int x, y; for (y = 0; y < 16 * BPS; y += 4 * BPS) { for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); + D += Disto4x4_C(a + x + y, b + x + y, w); } } return D; } +#endif // !WEBP_NEON_OMIT_C_CODE //------------------------------------------------------------------------------ // Quantization @@ -636,8 +650,8 @@ static const uint8_t kZigzag[16] = { }; // Simple quantization -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { +static int QuantizeBlock_C(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { int last = -1; int n; for (n = 0; n < 16; ++n) { @@ -662,13 +676,15 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16], return (last >= 0); } -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC +static int Quantize2Blocks_C(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { int nz; nz = VP8EncQuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; nz |= VP8EncQuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; return nz; } +#endif // !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC //------------------------------------------------------------------------------ // Block copy @@ -682,148 +698,14 @@ static WEBP_INLINE void Copy(const uint8_t* src, uint8_t* dst, int w, int h) { } } -static void Copy4x4(const uint8_t* src, uint8_t* dst) { +static void Copy4x4_C(const uint8_t* src, uint8_t* dst) { Copy(src, dst, 4, 4); } -static void Copy16x8(const uint8_t* src, uint8_t* dst) { +static void Copy16x8_C(const uint8_t* src, uint8_t* dst) { Copy(src, dst, 16, 8); } -//------------------------------------------------------------------------------ -// SSIM / PSNR - -// hat-shaped filter. Sum of coefficients is equal to 16. -static const uint32_t kWeight[2 * VP8_SSIM_KERNEL + 1] = { - 1, 2, 3, 4, 3, 2, 1 -}; -static const uint32_t kWeightSum = 16 * 16; // sum{kWeight}^2 - -static WEBP_INLINE double SSIMCalculation( - const VP8DistoStats* const stats, uint32_t N /*num samples*/) { - const uint32_t w2 = N * N; - const uint32_t C1 = 20 * w2; - const uint32_t C2 = 60 * w2; - const uint32_t C3 = 8 * 8 * w2; // 'dark' limit ~= 6 - const uint64_t xmxm = (uint64_t)stats->xm * stats->xm; - const uint64_t ymym = (uint64_t)stats->ym * stats->ym; - if (xmxm + ymym >= C3) { - const int64_t xmym = (int64_t)stats->xm * stats->ym; - const int64_t sxy = (int64_t)stats->xym * N - xmym; // can be negative - const uint64_t sxx = (uint64_t)stats->xxm * N - xmxm; - const uint64_t syy = (uint64_t)stats->yym * N - ymym; - // we descale by 8 to prevent overflow during the fnum/fden multiply. - const uint64_t num_S = (2 * (uint64_t)(sxy < 0 ? 0 : sxy) + C2) >> 8; - const uint64_t den_S = (sxx + syy + C2) >> 8; - const uint64_t fnum = (2 * xmym + C1) * num_S; - const uint64_t fden = (xmxm + ymym + C1) * den_S; - const double r = (double)fnum / fden; - assert(r >= 0. && r <= 1.0); - return r; - } - return 1.; // area is too dark to contribute meaningfully -} - -double VP8SSIMFromStats(const VP8DistoStats* const stats) { - return SSIMCalculation(stats, kWeightSum); -} - -double VP8SSIMFromStatsClipped(const VP8DistoStats* const stats) { - return SSIMCalculation(stats, stats->w); -} - -static double SSIMGetClipped_C(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2, - int xo, int yo, int W, int H) { - VP8DistoStats stats = { 0, 0, 0, 0, 0, 0 }; - const int ymin = (yo - VP8_SSIM_KERNEL < 0) ? 0 : yo - VP8_SSIM_KERNEL; - const int ymax = (yo + VP8_SSIM_KERNEL > H - 1) ? H - 1 - : yo + VP8_SSIM_KERNEL; - const int xmin = (xo - VP8_SSIM_KERNEL < 0) ? 0 : xo - VP8_SSIM_KERNEL; - const int xmax = (xo + VP8_SSIM_KERNEL > W - 1) ? W - 1 - : xo + VP8_SSIM_KERNEL; - int x, y; - src1 += ymin * stride1; - src2 += ymin * stride2; - for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) { - for (x = xmin; x <= xmax; ++x) { - const uint32_t w = kWeight[VP8_SSIM_KERNEL + x - xo] - * kWeight[VP8_SSIM_KERNEL + y - yo]; - const uint32_t s1 = src1[x]; - const uint32_t s2 = src2[x]; - stats.w += w; - stats.xm += w * s1; - stats.ym += w * s2; - stats.xxm += w * s1 * s1; - stats.xym += w * s1 * s2; - stats.yym += w * s2 * s2; - } - } - return VP8SSIMFromStatsClipped(&stats); -} - -static double SSIMGet_C(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2) { - VP8DistoStats stats = { 0, 0, 0, 0, 0, 0 }; - int x, y; - for (y = 0; y <= 2 * VP8_SSIM_KERNEL; ++y, src1 += stride1, src2 += stride2) { - for (x = 0; x <= 2 * VP8_SSIM_KERNEL; ++x) { - const uint32_t w = kWeight[x] * kWeight[y]; - const uint32_t s1 = src1[x]; - const uint32_t s2 = src2[x]; - stats.xm += w * s1; - stats.ym += w * s2; - stats.xxm += w * s1 * s1; - stats.xym += w * s1 * s2; - stats.yym += w * s2 * s2; - } - } - return VP8SSIMFromStats(&stats); -} - -//------------------------------------------------------------------------------ - -static uint32_t AccumulateSSE(const uint8_t* src1, - const uint8_t* src2, int len) { - int i; - uint32_t sse2 = 0; - assert(len <= 65535); // to ensure that accumulation fits within uint32_t - for (i = 0; i < len; ++i) { - const int32_t diff = src1[i] - src2[i]; - sse2 += diff * diff; - } - return sse2; -} - -//------------------------------------------------------------------------------ - -VP8SSIMGetFunc VP8SSIMGet; -VP8SSIMGetClippedFunc VP8SSIMGetClipped; -VP8AccumulateSSEFunc VP8AccumulateSSE; - -extern void VP8SSIMDspInitSSE2(void); - -static volatile VP8CPUInfo ssim_last_cpuinfo_used = - (VP8CPUInfo)&ssim_last_cpuinfo_used; - -WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) { - if (ssim_last_cpuinfo_used == VP8GetCPUInfo) return; - - VP8SSIMGetClipped = SSIMGetClipped_C; - VP8SSIMGet = SSIMGet_C; - - VP8AccumulateSSE = AccumulateSSE; - if (VP8GetCPUInfo != NULL) { -#if defined(WEBP_USE_SSE2) - if (VP8GetCPUInfo(kSSE2)) { - VP8SSIMDspInitSSE2(); - } -#endif - } - - ssim_last_cpuinfo_used = VP8GetCPUInfo; -} - //------------------------------------------------------------------------------ // Initialization @@ -868,26 +750,32 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) { InitTables(); // default C implementations - VP8CollectHistogram = CollectHistogram; - VP8ITransform = ITransform; - VP8FTransform = FTransform; - VP8FTransform2 = FTransform2; - VP8FTransformWHT = FTransformWHT; - VP8EncPredLuma4 = Intra4Preds; - VP8EncPredLuma16 = Intra16Preds; - VP8EncPredChroma8 = IntraChromaPreds; - VP8SSE16x16 = SSE16x16; - VP8SSE8x8 = SSE8x8; - VP8SSE16x8 = SSE16x8; - VP8SSE4x4 = SSE4x4; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; - VP8Mean16x4 = Mean16x4; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8EncQuantizeBlockWHT = QuantizeBlock; - VP8Copy4x4 = Copy4x4; - VP8Copy16x8 = Copy16x8; +#if !WEBP_NEON_OMIT_C_CODE + VP8ITransform = ITransform_C; + VP8FTransform = FTransform_C; + VP8FTransformWHT = FTransformWHT_C; + VP8TDisto4x4 = Disto4x4_C; + VP8TDisto16x16 = Disto16x16_C; + VP8CollectHistogram = CollectHistogram_C; + VP8SSE16x16 = SSE16x16_C; + VP8SSE16x8 = SSE16x8_C; + VP8SSE8x8 = SSE8x8_C; + VP8SSE4x4 = SSE4x4_C; +#endif + +#if !WEBP_NEON_OMIT_C_CODE || WEBP_NEON_WORK_AROUND_GCC + VP8EncQuantizeBlock = QuantizeBlock_C; + VP8EncQuantize2Blocks = Quantize2Blocks_C; +#endif + + VP8FTransform2 = FTransform2_C; + VP8EncPredLuma4 = Intra4Preds_C; + VP8EncPredLuma16 = Intra16Preds_C; + VP8EncPredChroma8 = IntraChromaPreds_C; + VP8Mean16x4 = Mean16x4_C; + VP8EncQuantizeBlockWHT = QuantizeBlock_C; + VP8Copy4x4 = Copy4x4_C; + VP8Copy16x8 = Copy16x8_C; // If defined, use CPUInfo() to overwrite some pointers with faster versions. if (VP8GetCPUInfo != NULL) { @@ -906,11 +794,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) { VP8EncDspInitAVX2(); } #endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8EncDspInitNEON(); - } -#endif #if defined(WEBP_USE_MIPS32) if (VP8GetCPUInfo(kMIPS32)) { VP8EncDspInitMIPS32(); @@ -927,5 +810,34 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInit(void) { } #endif } + +#if defined(WEBP_USE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8EncDspInitNEON(); + } +#endif + + assert(VP8ITransform != NULL); + assert(VP8FTransform != NULL); + assert(VP8FTransformWHT != NULL); + assert(VP8TDisto4x4 != NULL); + assert(VP8TDisto16x16 != NULL); + assert(VP8CollectHistogram != NULL); + assert(VP8SSE16x16 != NULL); + assert(VP8SSE16x8 != NULL); + assert(VP8SSE8x8 != NULL); + assert(VP8SSE4x4 != NULL); + assert(VP8EncQuantizeBlock != NULL); + assert(VP8EncQuantize2Blocks != NULL); + assert(VP8FTransform2 != NULL); + assert(VP8EncPredLuma4 != NULL); + assert(VP8EncPredLuma16 != NULL); + assert(VP8EncPredChroma8 != NULL); + assert(VP8Mean16x4 != NULL); + assert(VP8EncQuantizeBlockWHT != NULL); + assert(VP8Copy4x4 != NULL); + assert(VP8Copy16x8 != NULL); + enc_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/3rdparty/libwebp/dsp/enc_avx2.c b/3rdparty/libwebp/src/dsp/enc_avx2.c similarity index 96% rename from 3rdparty/libwebp/dsp/enc_avx2.c rename to 3rdparty/libwebp/src/dsp/enc_avx2.c index 93efb30b10..8bc5798fee 100644 --- a/3rdparty/libwebp/dsp/enc_avx2.c +++ b/3rdparty/libwebp/src/dsp/enc_avx2.c @@ -9,7 +9,7 @@ // // AVX2 version of speed-critical encoding functions. -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_AVX2) diff --git a/3rdparty/libwebp/dsp/enc_mips32.c b/3rdparty/libwebp/src/dsp/enc_mips32.c similarity index 94% rename from 3rdparty/libwebp/dsp/enc_mips32.c rename to 3rdparty/libwebp/src/dsp/enc_mips32.c index 752b14daf6..618f0fc0ee 100644 --- a/3rdparty/libwebp/dsp/enc_mips32.c +++ b/3rdparty/libwebp/src/dsp/enc_mips32.c @@ -13,13 +13,13 @@ // Jovan Zelincevic (jovan.zelincevic@imgtec.com) // Slobodan Prijic (slobodan.prijic@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS32) -#include "./mips_macro.h" -#include "../enc/vp8i_enc.h" -#include "../enc/cost_enc.h" +#include "src/dsp/mips_macro.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/cost_enc.h" static const int kC1 = 20091 + (1 << 16); static const int kC2 = 35468; @@ -113,8 +113,9 @@ static const int kC2 = 35468; "sb %[" #TEMP12 "], 3+" XSTR(BPS) "*" #A "(%[temp16]) \n\t" // Does one or two inverse transforms. -static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, - uint8_t* dst) { +static WEBP_INLINE void ITransformOne_MIPS32(const uint8_t* ref, + const int16_t* in, + uint8_t* dst) { int temp0, temp1, temp2, temp3, temp4, temp5, temp6; int temp7, temp8, temp9, temp10, temp11, temp12, temp13; int temp14, temp15, temp16, temp17, temp18, temp19, temp20; @@ -144,11 +145,11 @@ static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, ); } -static void ITransform(const uint8_t* ref, const int16_t* in, - uint8_t* dst, int do_two) { - ITransformOne(ref, in, dst); +static void ITransform_MIPS32(const uint8_t* ref, const int16_t* in, + uint8_t* dst, int do_two) { + ITransformOne_MIPS32(ref, in, dst); if (do_two) { - ITransformOne(ref + 4, in + 16, dst + 4); + ITransformOne_MIPS32(ref + 4, in + 16, dst + 4); } } @@ -187,8 +188,8 @@ static void ITransform(const uint8_t* ref, const int16_t* in, "sh %[temp5], " #J "(%[ppin]) \n\t" \ "sh %[level], " #N "(%[pout]) \n\t" -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { +static int QuantizeBlock_MIPS32(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { int temp0, temp1, temp2, temp3, temp4, temp5; int sign, coeff, level, i; int max_level = MAX_LEVEL; @@ -238,11 +239,11 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16], return 0; } -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { +static int Quantize2Blocks_MIPS32(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { int nz; - nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; - nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; + nz = QuantizeBlock_MIPS32(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= QuantizeBlock_MIPS32(in + 1 * 16, out + 1 * 16, mtx) << 1; return nz; } @@ -361,8 +362,8 @@ static int Quantize2Blocks(int16_t in[32], int16_t out[32], "msub %[temp6], %[temp0] \n\t" \ "msub %[temp7], %[temp1] \n\t" -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { +static int Disto4x4_MIPS32(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { int tmp[32]; int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; @@ -396,13 +397,13 @@ static int Disto4x4(const uint8_t* const a, const uint8_t* const b, #undef VERTICAL_PASS #undef HORIZONTAL_PASS -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { +static int Disto16x16_MIPS32(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { int D = 0; int x, y; for (y = 0; y < 16 * BPS; y += 4 * BPS) { for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); + D += Disto4x4_MIPS32(a + x + y, b + x + y, w); } } return D; @@ -478,7 +479,8 @@ static int Disto16x16(const uint8_t* const a, const uint8_t* const b, "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \ "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t" -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { +static void FTransform_MIPS32(const uint8_t* src, const uint8_t* ref, + int16_t* out) { int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; int temp9, temp10, temp11, temp12, temp13, temp14, temp15, temp16; int temp17, temp18, temp19, temp20; @@ -539,7 +541,7 @@ static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { GET_SSE_INNER(C, C + 1, C + 2, C + 3) \ GET_SSE_INNER(D, D + 1, D + 2, D + 3) -static int SSE16x16(const uint8_t* a, const uint8_t* b) { +static int SSE16x16_MIPS32(const uint8_t* a, const uint8_t* b) { int count; int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; @@ -573,7 +575,7 @@ static int SSE16x16(const uint8_t* a, const uint8_t* b) { return count; } -static int SSE16x8(const uint8_t* a, const uint8_t* b) { +static int SSE16x8_MIPS32(const uint8_t* a, const uint8_t* b) { int count; int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; @@ -599,7 +601,7 @@ static int SSE16x8(const uint8_t* a, const uint8_t* b) { return count; } -static int SSE8x8(const uint8_t* a, const uint8_t* b) { +static int SSE8x8_MIPS32(const uint8_t* a, const uint8_t* b) { int count; int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; @@ -621,7 +623,7 @@ static int SSE8x8(const uint8_t* a, const uint8_t* b) { return count; } -static int SSE4x4(const uint8_t* a, const uint8_t* b) { +static int SSE4x4_MIPS32(const uint8_t* a, const uint8_t* b) { int count; int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; @@ -651,17 +653,20 @@ static int SSE4x4(const uint8_t* a, const uint8_t* b) { extern void VP8EncDspInitMIPS32(void); WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPS32(void) { - VP8ITransform = ITransform; - VP8FTransform = FTransform; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; + VP8ITransform = ITransform_MIPS32; + VP8FTransform = FTransform_MIPS32; + + VP8EncQuantizeBlock = QuantizeBlock_MIPS32; + VP8EncQuantize2Blocks = Quantize2Blocks_MIPS32; + + VP8TDisto4x4 = Disto4x4_MIPS32; + VP8TDisto16x16 = Disto16x16_MIPS32; + #if !defined(WORK_AROUND_GCC) - VP8SSE16x16 = SSE16x16; - VP8SSE8x8 = SSE8x8; - VP8SSE16x8 = SSE16x8; - VP8SSE4x4 = SSE4x4; + VP8SSE16x16 = SSE16x16_MIPS32; + VP8SSE8x8 = SSE8x8_MIPS32; + VP8SSE16x8 = SSE16x8_MIPS32; + VP8SSE4x4 = SSE4x4_MIPS32; #endif } diff --git a/3rdparty/libwebp/dsp/enc_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/enc_mips_dsp_r2.c similarity index 96% rename from 3rdparty/libwebp/dsp/enc_mips_dsp_r2.c rename to 3rdparty/libwebp/src/dsp/enc_mips_dsp_r2.c index 6c8c1c6acd..9ddd895086 100644 --- a/3rdparty/libwebp/dsp/enc_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/enc_mips_dsp_r2.c @@ -12,13 +12,13 @@ // Author(s): Darko Laus (darko.laus@imgtec.com) // Mirko Raus (mirko.raus@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS_DSP_R2) -#include "./mips_macro.h" -#include "../enc/cost_enc.h" -#include "../enc/vp8i_enc.h" +#include "src/dsp/mips_macro.h" +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" static const int kC1 = 20091 + (1 << 16); static const int kC2 = 35468; @@ -141,7 +141,8 @@ static const int kC2 = 35468; "sh %[" #TEMP8 "], " #D "(%[temp20]) \n\t" \ "sh %[" #TEMP12 "], " #B "(%[temp20]) \n\t" -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { +static void FTransform_MIPSdspR2(const uint8_t* src, const uint8_t* ref, + int16_t* out) { const int c2217 = 2217; const int c5352 = 5352; int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8; @@ -238,16 +239,16 @@ static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, ); } -static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two) { +static void ITransform_MIPSdspR2(const uint8_t* ref, const int16_t* in, + uint8_t* dst, int do_two) { ITransformOne(ref, in, dst); if (do_two) { ITransformOne(ref + 4, in + 16, dst + 4); } } -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { +static int Disto4x4_MIPSdspR2(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9; int temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17; @@ -313,13 +314,14 @@ static int Disto4x4(const uint8_t* const a, const uint8_t* const b, return abs(temp3 - temp17) >> 5; } -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { +static int Disto16x16_MIPSdspR2(const uint8_t* const a, + const uint8_t* const b, + const uint16_t* const w) { int D = 0; int x, y; for (y = 0; y < 16 * BPS; y += 4 * BPS) { for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); + D += Disto4x4_MIPSdspR2(a + x + y, b + x + y, w); } } return D; @@ -1011,8 +1013,8 @@ static void HU4(uint8_t* dst, const uint8_t* top) { //------------------------------------------------------------------------------ // Chroma 8x8 prediction (paragraph 12.2) -static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { +static void IntraChromaPreds_MIPSdspR2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { // U block DCMode8(C8DC8 + dst, left, top); VerticalPred8(C8VE8 + dst, top); @@ -1031,8 +1033,8 @@ static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, //------------------------------------------------------------------------------ // luma 16x16 prediction (paragraph 12.3) -static void Intra16Preds(uint8_t* dst, - const uint8_t* left, const uint8_t* top) { +static void Intra16Preds_MIPSdspR2(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { DCMode16(I16DC16 + dst, left, top); VerticalPred16(I16VE16 + dst, top); HorizontalPred16(I16HE16 + dst, left); @@ -1041,7 +1043,7 @@ static void Intra16Preds(uint8_t* dst, // Left samples are top[-5 .. -2], top_left is top[-1], top are // located at top[0..3], and top right is top[4..7] -static void Intra4Preds(uint8_t* dst, const uint8_t* top) { +static void Intra4Preds_MIPSdspR2(uint8_t* dst, const uint8_t* top) { DC4(I4DC4 + dst, top); TM4(I4TM4 + dst, top); VE4(I4VE4 + dst, top); @@ -1077,7 +1079,7 @@ static void Intra4Preds(uint8_t* dst, const uint8_t* top) { GET_SSE_INNER(C) \ GET_SSE_INNER(D) -static int SSE16x16(const uint8_t* a, const uint8_t* b) { +static int SSE16x16_MIPSdspR2(const uint8_t* a, const uint8_t* b) { int count; int temp0, temp1, temp2, temp3; __asm__ volatile ( @@ -1107,7 +1109,7 @@ static int SSE16x16(const uint8_t* a, const uint8_t* b) { return count; } -static int SSE16x8(const uint8_t* a, const uint8_t* b) { +static int SSE16x8_MIPSdspR2(const uint8_t* a, const uint8_t* b) { int count; int temp0, temp1, temp2, temp3; __asm__ volatile ( @@ -1129,7 +1131,7 @@ static int SSE16x8(const uint8_t* a, const uint8_t* b) { return count; } -static int SSE8x8(const uint8_t* a, const uint8_t* b) { +static int SSE8x8_MIPSdspR2(const uint8_t* a, const uint8_t* b) { int count; int temp0, temp1, temp2, temp3; __asm__ volatile ( @@ -1147,7 +1149,7 @@ static int SSE8x8(const uint8_t* a, const uint8_t* b) { return count; } -static int SSE4x4(const uint8_t* a, const uint8_t* b) { +static int SSE4x4_MIPSdspR2(const uint8_t* a, const uint8_t* b) { int count; int temp0, temp1, temp2, temp3; __asm__ volatile ( @@ -1270,8 +1272,8 @@ static int SSE4x4(const uint8_t* a, const uint8_t* b) { "usw $0, " #J "(%[ppin]) \n\t" \ "3: \n\t" -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { +static int QuantizeBlock_MIPSdspR2(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { int temp0, temp1, temp2, temp3, temp4, temp5,temp6; int sign, coeff, level; int max_level = MAX_LEVEL; @@ -1311,11 +1313,11 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16], return (ret != 0); } -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { +static int Quantize2Blocks_MIPSdspR2(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { int nz; - nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; - nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; + nz = QuantizeBlock_MIPSdspR2(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= QuantizeBlock_MIPSdspR2(in + 1 * 16, out + 1 * 16, mtx) << 1; return nz; } @@ -1358,7 +1360,7 @@ static int Quantize2Blocks(int16_t in[32], int16_t out[32], "usw %[" #TEMP4 "], " #C "(%[out]) \n\t" \ "usw %[" #TEMP6 "], " #D "(%[out]) \n\t" -static void FTransformWHT(const int16_t* in, int16_t* out) { +static void FTransformWHT_MIPSdspR2(const int16_t* in, int16_t* out) { int temp0, temp1, temp2, temp3, temp4; int temp5, temp6, temp7, temp8, temp9; @@ -1450,9 +1452,9 @@ static void FTransformWHT(const int16_t* in, int16_t* out) { "addiu %[temp8], %[temp8], 1 \n\t" \ "sw %[temp8], 0(%[temp3]) \n\t" -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { +static void CollectHistogram_MIPSdspR2(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { int j; int distribution[MAX_COEFF_THRESH + 1] = { 0 }; const int max_coeff = (MAX_COEFF_THRESH << 16) + MAX_COEFF_THRESH; @@ -1484,23 +1486,28 @@ static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, extern void VP8EncDspInitMIPSdspR2(void); WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMIPSdspR2(void) { - VP8FTransform = FTransform; - VP8ITransform = ITransform; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; - VP8EncPredLuma16 = Intra16Preds; - VP8EncPredChroma8 = IntraChromaPreds; - VP8EncPredLuma4 = Intra4Preds; + VP8FTransform = FTransform_MIPSdspR2; + VP8FTransformWHT = FTransformWHT_MIPSdspR2; + VP8ITransform = ITransform_MIPSdspR2; + + VP8TDisto4x4 = Disto4x4_MIPSdspR2; + VP8TDisto16x16 = Disto16x16_MIPSdspR2; + + VP8EncPredLuma16 = Intra16Preds_MIPSdspR2; + VP8EncPredChroma8 = IntraChromaPreds_MIPSdspR2; + VP8EncPredLuma4 = Intra4Preds_MIPSdspR2; + #if !defined(WORK_AROUND_GCC) - VP8SSE16x16 = SSE16x16; - VP8SSE8x8 = SSE8x8; - VP8SSE16x8 = SSE16x8; - VP8SSE4x4 = SSE4x4; + VP8SSE16x16 = SSE16x16_MIPSdspR2; + VP8SSE8x8 = SSE8x8_MIPSdspR2; + VP8SSE16x8 = SSE16x8_MIPSdspR2; + VP8SSE4x4 = SSE4x4_MIPSdspR2; #endif - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8FTransformWHT = FTransformWHT; - VP8CollectHistogram = CollectHistogram; + + VP8EncQuantizeBlock = QuantizeBlock_MIPSdspR2; + VP8EncQuantize2Blocks = Quantize2Blocks_MIPSdspR2; + + VP8CollectHistogram = CollectHistogram_MIPSdspR2; } #else // !WEBP_USE_MIPS_DSP_R2 diff --git a/3rdparty/libwebp/dsp/enc_msa.c b/3rdparty/libwebp/src/dsp/enc_msa.c similarity index 91% rename from 3rdparty/libwebp/dsp/enc_msa.c rename to 3rdparty/libwebp/src/dsp/enc_msa.c index 909b46d5d9..6f85add4bb 100644 --- a/3rdparty/libwebp/dsp/enc_msa.c +++ b/3rdparty/libwebp/src/dsp/enc_msa.c @@ -11,13 +11,13 @@ // // Author: Prashant Patil (prashant.patil@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MSA) #include -#include "./msa_macro.h" -#include "../enc/vp8i_enc.h" +#include "src/dsp/msa_macro.h" +#include "src/enc/vp8i_enc.h" //------------------------------------------------------------------------------ // Transforms @@ -69,20 +69,21 @@ static WEBP_INLINE void ITransformOne(const uint8_t* ref, const int16_t* in, ST4x4_UB(res0, res0, 3, 2, 1, 0, dst, BPS); } -static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two) { +static void ITransform_MSA(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two) { ITransformOne(ref, in, dst); if (do_two) { ITransformOne(ref + 4, in + 16, dst + 4); } } -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { +static void FTransform_MSA(const uint8_t* src, const uint8_t* ref, + int16_t* out) { uint64_t out0, out1, out2, out3; uint32_t in0, in1, in2, in3; v4i32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; v8i16 t0, t1, t2, t3; - v16u8 srcl0, srcl1, src0, src1; + v16u8 srcl0, srcl1, src0 = { 0 }, src1 = { 0 }; const v8i16 mask0 = { 0, 4, 8, 12, 1, 5, 9, 13 }; const v8i16 mask1 = { 3, 7, 11, 15, 2, 6, 10, 14 }; const v8i16 mask2 = { 4, 0, 5, 1, 6, 2, 7, 3 }; @@ -130,7 +131,7 @@ static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { SD4(out0, out1, out2, out3, out, 8); } -static void FTransformWHT(const int16_t* in, int16_t* out) { +static void FTransformWHT_MSA(const int16_t* in, int16_t* out) { v8i16 in0 = { 0 }; v8i16 in1 = { 0 }; v8i16 tmp0, tmp1, tmp2, tmp3; @@ -167,10 +168,10 @@ static void FTransformWHT(const int16_t* in, int16_t* out) { ST_SH2(out0, out1, out, 8); } -static int TTransform(const uint8_t* in, const uint16_t* w) { +static int TTransform_MSA(const uint8_t* in, const uint16_t* w) { int sum; uint32_t in0_m, in1_m, in2_m, in3_m; - v16i8 src0; + v16i8 src0 = { 0 }; v8i16 in0, in1, tmp0, tmp1, tmp2, tmp3; v4i32 dst0, dst1; const v16i8 zero = { 0 }; @@ -199,20 +200,20 @@ static int TTransform(const uint8_t* in, const uint16_t* w) { return sum; } -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - const int sum1 = TTransform(a, w); - const int sum2 = TTransform(b, w); +static int Disto4x4_MSA(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int sum1 = TTransform_MSA(a, w); + const int sum2 = TTransform_MSA(b, w); return abs(sum2 - sum1) >> 5; } -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { +static int Disto16x16_MSA(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { int D = 0; int x, y; for (y = 0; y < 16 * BPS; y += 4 * BPS) { for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); + D += Disto4x4_MSA(a + x + y, b + x + y, w); } } return D; @@ -221,9 +222,9 @@ static int Disto16x16(const uint8_t* const a, const uint8_t* const b, //------------------------------------------------------------------------------ // Histogram -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { +static void CollectHistogram_MSA(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { int j; int distribution[MAX_COEFF_THRESH + 1] = { 0 }; for (j = start_block; j < end_block; ++j) { @@ -259,8 +260,9 @@ static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, #define AVG2(a, b) (((a) + (b) + 1) >> 1) static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical + const v16u8 A1 = { 0 }; const uint64_t val_m = LD(top - 1); - const v16u8 A = (v16u8)__msa_insert_d((v2i64)A, 0, val_m); + const v16u8 A = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m); const v16u8 B = SLDI_UB(A, A, 1); const v16u8 C = SLDI_UB(A, A, 2); const v16u8 AC = __msa_ave_u_b(A, C); @@ -292,8 +294,9 @@ static WEBP_INLINE void DC4(uint8_t* dst, const uint8_t* top) { } static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { + const v16u8 A2 = { 0 }; const uint64_t val_m = LD(top - 5); - const v16u8 A1 = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m); + const v16u8 A1 = (v16u8)__msa_insert_d((v2i64)A2, 0, val_m); const v16u8 A = (v16u8)__msa_insert_b((v16i8)A1, 8, top[3]); const v16u8 B = SLDI_UB(A, A, 1); const v16u8 C = SLDI_UB(A, A, 2); @@ -311,8 +314,9 @@ static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { } static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) { + const v16u8 A1 = { 0 }; const uint64_t val_m = LD(top); - const v16u8 A = (v16u8)__msa_insert_d((v2i64)A, 0, val_m); + const v16u8 A = (v16u8)__msa_insert_d((v2i64)A1, 0, val_m); const v16u8 B = SLDI_UB(A, A, 1); const v16u8 C1 = SLDI_UB(A, A, 2); const v16u8 C = (v16u8)__msa_insert_b((v16i8)C1, 6, top[7]); @@ -427,7 +431,7 @@ static WEBP_INLINE void TM4(uint8_t* dst, const uint8_t* top) { #undef AVG3 #undef AVG2 -static void Intra4Preds(uint8_t* dst, const uint8_t* top) { +static void Intra4Preds_MSA(uint8_t* dst, const uint8_t* top) { DC4(I4DC4 + dst, top); TM4(I4TM4 + dst, top); VE4(I4VE4 + dst, top); @@ -544,8 +548,8 @@ static WEBP_INLINE void DCMode16x16(uint8_t* dst, const uint8_t* left, STORE16x16(out, dst); } -static void Intra16Preds(uint8_t* dst, - const uint8_t* left, const uint8_t* top) { +static void Intra16Preds_MSA(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { DCMode16x16(I16DC16 + dst, left, top); VerticalPred16x16(I16VE16 + dst, top); HorizontalPred16x16(I16HE16 + dst, left); @@ -645,7 +649,7 @@ static WEBP_INLINE void TrueMotion8x8(uint8_t* dst, const uint8_t* left, static WEBP_INLINE void DCMode8x8(uint8_t* dst, const uint8_t* left, const uint8_t* top) { uint64_t out; - v16u8 src; + v16u8 src = { 0 }; if (top != NULL && left != NULL) { const uint64_t left_m = LD(left); const uint64_t top_m = LD(top); @@ -666,8 +670,8 @@ static WEBP_INLINE void DCMode8x8(uint8_t* dst, const uint8_t* left, STORE8x8(out, dst); } -static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { +static void IntraChromaPreds_MSA(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { // U block DCMode8x8(C8DC8 + dst, left, top); VerticalPred8x8(C8VE8 + dst, top); @@ -708,7 +712,7 @@ static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, DPADD_SH2_SW(tmp2, tmp3, tmp2, tmp3, out2, out3); \ } while (0) -static int SSE16x16(const uint8_t* a, const uint8_t* b) { +static int SSE16x16_MSA(const uint8_t* a, const uint8_t* b) { uint32_t sum; v16u8 src0, src1, src2, src3, src4, src5, src6, src7; v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7; @@ -735,7 +739,7 @@ static int SSE16x16(const uint8_t* a, const uint8_t* b) { return sum; } -static int SSE16x8(const uint8_t* a, const uint8_t* b) { +static int SSE16x8_MSA(const uint8_t* a, const uint8_t* b) { uint32_t sum; v16u8 src0, src1, src2, src3, src4, src5, src6, src7; v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7; @@ -754,7 +758,7 @@ static int SSE16x8(const uint8_t* a, const uint8_t* b) { return sum; } -static int SSE8x8(const uint8_t* a, const uint8_t* b) { +static int SSE8x8_MSA(const uint8_t* a, const uint8_t* b) { uint32_t sum; v16u8 src0, src1, src2, src3, src4, src5, src6, src7; v16u8 ref0, ref1, ref2, ref3, ref4, ref5, ref6, ref7; @@ -774,10 +778,10 @@ static int SSE8x8(const uint8_t* a, const uint8_t* b) { return sum; } -static int SSE4x4(const uint8_t* a, const uint8_t* b) { +static int SSE4x4_MSA(const uint8_t* a, const uint8_t* b) { uint32_t sum = 0; uint32_t src0, src1, src2, src3, ref0, ref1, ref2, ref3; - v16u8 src, ref, tmp0, tmp1; + v16u8 src = { 0 }, ref = { 0 }, tmp0, tmp1; v8i16 diff0, diff1; v4i32 out0, out1; @@ -796,8 +800,8 @@ static int SSE4x4(const uint8_t* a, const uint8_t* b) { //------------------------------------------------------------------------------ // Quantization -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { +static int QuantizeBlock_MSA(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { int sum; v8i16 in0, in1, sh0, sh1, out0, out1; v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, sign0, sign1; @@ -828,7 +832,7 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16], tmp1 = (tmp3 > maxlevel); tmp2 = (v8i16)__msa_bmnz_v((v16u8)tmp2, (v16u8)maxlevel, (v16u8)tmp0); tmp3 = (v8i16)__msa_bmnz_v((v16u8)tmp3, (v16u8)maxlevel, (v16u8)tmp1); - SUB2(0, tmp2, 0, tmp3, tmp0, tmp1); + SUB2(zero, tmp2, zero, tmp3, tmp0, tmp1); tmp2 = (v8i16)__msa_bmnz_v((v16u8)tmp2, (v16u8)tmp0, (v16u8)sign0); tmp3 = (v8i16)__msa_bmnz_v((v16u8)tmp3, (v16u8)tmp1, (v16u8)sign1); LD_SW4(&mtx->zthresh_[0], 4, t0, t1, t2, t3); // zthresh @@ -849,8 +853,8 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16], return (sum > 0); } -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { +static int Quantize2Blocks_MSA(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { int nz; nz = VP8EncQuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; nz |= VP8EncQuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; @@ -863,26 +867,26 @@ static int Quantize2Blocks(int16_t in[32], int16_t out[32], extern void VP8EncDspInitMSA(void); WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitMSA(void) { - VP8ITransform = ITransform; - VP8FTransform = FTransform; - VP8FTransformWHT = FTransformWHT; + VP8ITransform = ITransform_MSA; + VP8FTransform = FTransform_MSA; + VP8FTransformWHT = FTransformWHT_MSA; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; - VP8CollectHistogram = CollectHistogram; + VP8TDisto4x4 = Disto4x4_MSA; + VP8TDisto16x16 = Disto16x16_MSA; + VP8CollectHistogram = CollectHistogram_MSA; - VP8EncPredLuma4 = Intra4Preds; - VP8EncPredLuma16 = Intra16Preds; - VP8EncPredChroma8 = IntraChromaPreds; + VP8EncPredLuma4 = Intra4Preds_MSA; + VP8EncPredLuma16 = Intra16Preds_MSA; + VP8EncPredChroma8 = IntraChromaPreds_MSA; - VP8SSE16x16 = SSE16x16; - VP8SSE16x8 = SSE16x8; - VP8SSE8x8 = SSE8x8; - VP8SSE4x4 = SSE4x4; + VP8SSE16x16 = SSE16x16_MSA; + VP8SSE16x8 = SSE16x8_MSA; + VP8SSE8x8 = SSE8x8_MSA; + VP8SSE4x4 = SSE4x4_MSA; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8EncQuantizeBlockWHT = QuantizeBlock; + VP8EncQuantizeBlock = QuantizeBlock_MSA; + VP8EncQuantize2Blocks = Quantize2Blocks_MSA; + VP8EncQuantizeBlockWHT = QuantizeBlock_MSA; } #else // !WEBP_USE_MSA diff --git a/3rdparty/libwebp/dsp/enc_neon.c b/3rdparty/libwebp/src/dsp/enc_neon.c similarity index 84% rename from 3rdparty/libwebp/dsp/enc_neon.c rename to 3rdparty/libwebp/src/dsp/enc_neon.c index 6a078d632d..43bf1245c5 100644 --- a/3rdparty/libwebp/dsp/enc_neon.c +++ b/3rdparty/libwebp/src/dsp/enc_neon.c @@ -11,14 +11,14 @@ // // adapted from libvpx (http://www.webmproject.org/code/) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_NEON) #include -#include "./neon.h" -#include "../enc/vp8i_enc.h" +#include "src/dsp/neon.h" +#include "src/enc/vp8i_enc.h" //------------------------------------------------------------------------------ // Transforms (Paragraph 14.4) @@ -37,15 +37,15 @@ static const int16_t kC2 = 17734; // half of kC2, actually. See comment above. #if defined(WEBP_USE_INTRINSICS) // Treats 'v' as an uint8x8_t and zero extends to an int16x8_t. -static WEBP_INLINE int16x8_t ConvertU8ToS16(uint32x2_t v) { +static WEBP_INLINE int16x8_t ConvertU8ToS16_NEON(uint32x2_t v) { return vreinterpretq_s16_u16(vmovl_u8(vreinterpret_u8_u32(v))); } // Performs unsigned 8b saturation on 'dst01' and 'dst23' storing the result // to the corresponding rows of 'dst'. -static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst, - const int16x8_t dst01, - const int16x8_t dst23) { +static WEBP_INLINE void SaturateAndStore4x4_NEON(uint8_t* const dst, + const int16x8_t dst01, + const int16x8_t dst23) { // Unsigned saturate to 8b. const uint8x8_t dst01_u8 = vqmovun_s16(dst01); const uint8x8_t dst23_u8 = vqmovun_s16(dst23); @@ -57,8 +57,10 @@ static WEBP_INLINE void SaturateAndStore4x4(uint8_t* const dst, vst1_lane_u32((uint32_t*)(dst + 3 * BPS), vreinterpret_u32_u8(dst23_u8), 1); } -static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23, - const uint8_t* const ref, uint8_t* const dst) { +static WEBP_INLINE void Add4x4_NEON(const int16x8_t row01, + const int16x8_t row23, + const uint8_t* const ref, + uint8_t* const dst) { uint32x2_t dst01 = vdup_n_u32(0); uint32x2_t dst23 = vdup_n_u32(0); @@ -70,19 +72,20 @@ static WEBP_INLINE void Add4x4(const int16x8_t row01, const int16x8_t row23, { // Convert to 16b. - const int16x8_t dst01_s16 = ConvertU8ToS16(dst01); - const int16x8_t dst23_s16 = ConvertU8ToS16(dst23); + const int16x8_t dst01_s16 = ConvertU8ToS16_NEON(dst01); + const int16x8_t dst23_s16 = ConvertU8ToS16_NEON(dst23); // Descale with rounding. const int16x8_t out01 = vrsraq_n_s16(dst01_s16, row01, 3); const int16x8_t out23 = vrsraq_n_s16(dst23_s16, row23, 3); // Add the inverse transform. - SaturateAndStore4x4(dst, out01, out23); + SaturateAndStore4x4_NEON(dst, out01, out23); } } -static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1, - int16x8x2_t* const out) { +static WEBP_INLINE void Transpose8x2_NEON(const int16x8_t in0, + const int16x8_t in1, + int16x8x2_t* const out) { // a0 a1 a2 a3 | b0 b1 b2 b3 => a0 b0 c0 d0 | a1 b1 c1 d1 // c0 c1 c2 c3 | d0 d1 d2 d3 a2 b2 c2 d2 | a3 b3 c3 d3 const int16x8x2_t tmp0 = vzipq_s16(in0, in1); // a0 c0 a1 c1 a2 c2 ... @@ -90,7 +93,7 @@ static WEBP_INLINE void Transpose8x2(const int16x8_t in0, const int16x8_t in1, *out = vzipq_s16(tmp0.val[0], tmp0.val[1]); } -static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) { +static WEBP_INLINE void TransformPass_NEON(int16x8x2_t* const rows) { // {rows} = in0 | in4 // in8 | in12 // B1 = in4 | in12 @@ -113,22 +116,22 @@ static WEBP_INLINE void TransformPass(int16x8x2_t* const rows) { const int16x8_t E0 = vqaddq_s16(D0, D1); // a+d | b+c const int16x8_t E_tmp = vqsubq_s16(D0, D1); // a-d | b-c const int16x8_t E1 = vcombine_s16(vget_high_s16(E_tmp), vget_low_s16(E_tmp)); - Transpose8x2(E0, E1, rows); + Transpose8x2_NEON(E0, E1, rows); } -static void ITransformOne(const uint8_t* ref, - const int16_t* in, uint8_t* dst) { +static void ITransformOne_NEON(const uint8_t* ref, + const int16_t* in, uint8_t* dst) { int16x8x2_t rows; INIT_VECTOR2(rows, vld1q_s16(in + 0), vld1q_s16(in + 8)); - TransformPass(&rows); - TransformPass(&rows); - Add4x4(rows.val[0], rows.val[1], ref, dst); + TransformPass_NEON(&rows); + TransformPass_NEON(&rows); + Add4x4_NEON(rows.val[0], rows.val[1], ref, dst); } #else -static void ITransformOne(const uint8_t* ref, - const int16_t* in, uint8_t* dst) { +static void ITransformOne_NEON(const uint8_t* ref, + const int16_t* in, uint8_t* dst) { const int kBPS = BPS; const int16_t kC1C2[] = { kC1, kC2, 0, 0 }; @@ -243,16 +246,16 @@ static void ITransformOne(const uint8_t* ref, #endif // WEBP_USE_INTRINSICS -static void ITransform(const uint8_t* ref, - const int16_t* in, uint8_t* dst, int do_two) { - ITransformOne(ref, in, dst); +static void ITransform_NEON(const uint8_t* ref, + const int16_t* in, uint8_t* dst, int do_two) { + ITransformOne_NEON(ref, in, dst); if (do_two) { - ITransformOne(ref + 4, in + 16, dst + 4); + ITransformOne_NEON(ref + 4, in + 16, dst + 4); } } // Load all 4x4 pixels into a single uint8x16_t variable. -static uint8x16_t Load4x4(const uint8_t* src) { +static uint8x16_t Load4x4_NEON(const uint8_t* src) { uint32x4_t out = vdupq_n_u32(0); out = vld1q_lane_u32((const uint32_t*)(src + 0 * BPS), out, 0); out = vld1q_lane_u32((const uint32_t*)(src + 1 * BPS), out, 1); @@ -265,10 +268,12 @@ static uint8x16_t Load4x4(const uint8_t* src) { #if defined(WEBP_USE_INTRINSICS) -static WEBP_INLINE void Transpose4x4_S16(const int16x4_t A, const int16x4_t B, - const int16x4_t C, const int16x4_t D, - int16x8_t* const out01, - int16x8_t* const out32) { +static WEBP_INLINE void Transpose4x4_S16_NEON(const int16x4_t A, + const int16x4_t B, + const int16x4_t C, + const int16x4_t D, + int16x8_t* const out01, + int16x8_t* const out32) { const int16x4x2_t AB = vtrn_s16(A, B); const int16x4x2_t CD = vtrn_s16(C, D); const int32x2x2_t tmp02 = vtrn_s32(vreinterpret_s32_s16(AB.val[0]), @@ -283,24 +288,24 @@ static WEBP_INLINE void Transpose4x4_S16(const int16x4_t A, const int16x4_t B, vreinterpret_s64_s32(tmp02.val[1]))); } -static WEBP_INLINE int16x8_t DiffU8ToS16(const uint8x8_t a, - const uint8x8_t b) { +static WEBP_INLINE int16x8_t DiffU8ToS16_NEON(const uint8x8_t a, + const uint8x8_t b) { return vreinterpretq_s16_u16(vsubl_u8(a, b)); } -static void FTransform(const uint8_t* src, const uint8_t* ref, - int16_t* out) { +static void FTransform_NEON(const uint8_t* src, const uint8_t* ref, + int16_t* out) { int16x8_t d0d1, d3d2; // working 4x4 int16 variables { - const uint8x16_t S0 = Load4x4(src); - const uint8x16_t R0 = Load4x4(ref); - const int16x8_t D0D1 = DiffU8ToS16(vget_low_u8(S0), vget_low_u8(R0)); - const int16x8_t D2D3 = DiffU8ToS16(vget_high_u8(S0), vget_high_u8(R0)); + const uint8x16_t S0 = Load4x4_NEON(src); + const uint8x16_t R0 = Load4x4_NEON(ref); + const int16x8_t D0D1 = DiffU8ToS16_NEON(vget_low_u8(S0), vget_low_u8(R0)); + const int16x8_t D2D3 = DiffU8ToS16_NEON(vget_high_u8(S0), vget_high_u8(R0)); const int16x4_t D0 = vget_low_s16(D0D1); const int16x4_t D1 = vget_high_s16(D0D1); const int16x4_t D2 = vget_low_s16(D2D3); const int16x4_t D3 = vget_high_s16(D2D3); - Transpose4x4_S16(D0, D1, D2, D3, &d0d1, &d3d2); + Transpose4x4_S16_NEON(D0, D1, D2, D3, &d0d1, &d3d2); } { // 1rst pass const int32x4_t kCst937 = vdupq_n_s32(937); @@ -318,7 +323,7 @@ static void FTransform(const uint8_t* src, const uint8_t* ref, const int32x4_t a3_m_a2 = vmlsl_n_s16(a3_2217, vget_high_s16(a3a2), 5352); const int16x4_t tmp1 = vshrn_n_s32(vaddq_s32(a2_p_a3, kCst1812), 9); const int16x4_t tmp3 = vshrn_n_s32(vaddq_s32(a3_m_a2, kCst937), 9); - Transpose4x4_S16(tmp0, tmp1, tmp2, tmp3, &d0d1, &d3d2); + Transpose4x4_S16_NEON(tmp0, tmp1, tmp2, tmp3, &d0d1, &d3d2); } { // 2nd pass // the (1<<16) addition is for the replacement: a3!=0 <-> 1-(a3==0) @@ -358,8 +363,8 @@ static const int32_t kCoeff32[] = { 51000, 51000, 51000, 51000 }; -static void FTransform(const uint8_t* src, const uint8_t* ref, - int16_t* out) { +static void FTransform_NEON(const uint8_t* src, const uint8_t* ref, + int16_t* out) { const int kBPS = BPS; const uint8_t* src_ptr = src; const uint8_t* ref_ptr = ref; @@ -478,7 +483,7 @@ static void FTransform(const uint8_t* src, const uint8_t* ref, src += stride; \ } while (0) -static void FTransformWHT(const int16_t* src, int16_t* out) { +static void FTransformWHT_NEON(const int16_t* src, int16_t* out) { const int stride = 16; const int16x4_t zero = vdup_n_s16(0); int32x4x4_t tmp0; @@ -516,7 +521,7 @@ static void FTransformWHT(const int16_t* src, int16_t* out) { tmp0.val[3] = vsubq_s32(a0, a1); } { - const int32x4x4_t tmp1 = Transpose4x4(tmp0); + const int32x4x4_t tmp1 = Transpose4x4_NEON(tmp0); // a0 = tmp[0 + i] + tmp[ 8 + i] // a1 = tmp[4 + i] + tmp[12 + i] // a2 = tmp[4 + i] - tmp[12 + i] @@ -560,7 +565,7 @@ static void FTransformWHT(const int16_t* src, int16_t* out) { // a 26ae, b 26ae // a 37bf, b 37bf // -static WEBP_INLINE int16x8x4_t DistoTranspose4x4S16(int16x8x4_t q4_in) { +static WEBP_INLINE int16x8x4_t DistoTranspose4x4S16_NEON(int16x8x4_t q4_in) { const int16x8x2_t q2_tmp0 = vtrnq_s16(q4_in.val[0], q4_in.val[1]); const int16x8x2_t q2_tmp1 = vtrnq_s16(q4_in.val[2], q4_in.val[3]); const int32x4x2_t q2_tmp2 = vtrnq_s32(vreinterpretq_s32_s16(q2_tmp0.val[0]), @@ -574,7 +579,8 @@ static WEBP_INLINE int16x8x4_t DistoTranspose4x4S16(int16x8x4_t q4_in) { return q4_in; } -static WEBP_INLINE int16x8x4_t DistoHorizontalPass(const int16x8x4_t q4_in) { +static WEBP_INLINE int16x8x4_t DistoHorizontalPass_NEON( + const int16x8x4_t q4_in) { // {a0, a1} = {in[0] + in[2], in[1] + in[3]} // {a3, a2} = {in[0] - in[2], in[1] - in[3]} const int16x8_t q_a0 = vaddq_s16(q4_in.val[0], q4_in.val[2]); @@ -593,7 +599,7 @@ static WEBP_INLINE int16x8x4_t DistoHorizontalPass(const int16x8x4_t q4_in) { return q4_out; } -static WEBP_INLINE int16x8x4_t DistoVerticalPass(const uint8x8x4_t q4_in) { +static WEBP_INLINE int16x8x4_t DistoVerticalPass_NEON(const uint8x8x4_t q4_in) { const int16x8_t q_a0 = vreinterpretq_s16_u16(vaddl_u8(q4_in.val[0], q4_in.val[2])); const int16x8_t q_a1 = vreinterpretq_s16_u16(vaddl_u8(q4_in.val[1], @@ -610,7 +616,7 @@ static WEBP_INLINE int16x8x4_t DistoVerticalPass(const uint8x8x4_t q4_in) { return q4_out; } -static WEBP_INLINE int16x4x4_t DistoLoadW(const uint16_t* w) { +static WEBP_INLINE int16x4x4_t DistoLoadW_NEON(const uint16_t* w) { const uint16x8_t q_w07 = vld1q_u16(&w[0]); const uint16x8_t q_w8f = vld1q_u16(&w[8]); int16x4x4_t d4_w; @@ -622,8 +628,8 @@ static WEBP_INLINE int16x4x4_t DistoLoadW(const uint16_t* w) { return d4_w; } -static WEBP_INLINE int32x2_t DistoSum(const int16x8x4_t q4_in, - const int16x4x4_t d4_w) { +static WEBP_INLINE int32x2_t DistoSum_NEON(const int16x8x4_t q4_in, + const int16x4x4_t d4_w) { int32x2_t d_sum; // sum += w[ 0] * abs(b0); // sum += w[ 4] * abs(b1); @@ -652,8 +658,8 @@ static WEBP_INLINE int32x2_t DistoSum(const int16x8x4_t q4_in, // Hadamard transform // Returns the weighted sum of the absolute value of transformed coefficients. // w[] contains a row-major 4 by 4 symmetric matrix. -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { +static int Disto4x4_NEON(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { uint32x2_t d_in_ab_0123 = vdup_n_u32(0); uint32x2_t d_in_ab_4567 = vdup_n_u32(0); uint32x2_t d_in_ab_89ab = vdup_n_u32(0); @@ -679,12 +685,12 @@ static int Disto4x4(const uint8_t* const a, const uint8_t* const b, // Vertical pass first to avoid a transpose (vertical and horizontal passes // are commutative because w/kWeightY is symmetric) and subsequent // transpose. - const int16x8x4_t q4_v = DistoVerticalPass(d4_in); - const int16x4x4_t d4_w = DistoLoadW(w); + const int16x8x4_t q4_v = DistoVerticalPass_NEON(d4_in); + const int16x4x4_t d4_w = DistoLoadW_NEON(w); // horizontal pass - const int16x8x4_t q4_t = DistoTranspose4x4S16(q4_v); - const int16x8x4_t q4_h = DistoHorizontalPass(q4_t); - int32x2_t d_sum = DistoSum(q4_h, d4_w); + const int16x8x4_t q4_t = DistoTranspose4x4S16_NEON(q4_v); + const int16x8x4_t q4_h = DistoHorizontalPass_NEON(q4_t); + int32x2_t d_sum = DistoSum_NEON(q4_h, d4_w); // abs(sum2 - sum1) >> 5 d_sum = vabs_s32(d_sum); @@ -694,13 +700,13 @@ static int Disto4x4(const uint8_t* const a, const uint8_t* const b, } #undef LOAD_LANE_32b -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { +static int Disto16x16_NEON(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { int D = 0; int x, y; for (y = 0; y < 16 * BPS; y += 4 * BPS) { for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); + D += Disto4x4_NEON(a + x + y, b + x + y, w); } } return D; @@ -708,15 +714,15 @@ static int Disto16x16(const uint8_t* const a, const uint8_t* const b, //------------------------------------------------------------------------------ -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { +static void CollectHistogram_NEON(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { const uint16x8_t max_coeff_thresh = vdupq_n_u16(MAX_COEFF_THRESH); int j; int distribution[MAX_COEFF_THRESH + 1] = { 0 }; for (j = start_block; j < end_block; ++j) { int16_t out[16]; - FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + FTransform_NEON(ref + VP8DspScan[j], pred + VP8DspScan[j], out); { int k; const int16x8_t a0 = vld1q_s16(out + 0); @@ -740,9 +746,9 @@ static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, //------------------------------------------------------------------------------ -static WEBP_INLINE void AccumulateSSE16(const uint8_t* const a, - const uint8_t* const b, - uint32x4_t* const sum) { +static WEBP_INLINE void AccumulateSSE16_NEON(const uint8_t* const a, + const uint8_t* const b, + uint32x4_t* const sum) { const uint8x16_t a0 = vld1q_u8(a); const uint8x16_t b0 = vld1q_u8(b); const uint8x16_t abs_diff = vabdq_u8(a0, b0); @@ -757,7 +763,7 @@ static WEBP_INLINE void AccumulateSSE16(const uint8_t* const a, } // Horizontal sum of all four uint32_t values in 'sum'. -static int SumToInt(uint32x4_t sum) { +static int SumToInt_NEON(uint32x4_t sum) { const uint64x2_t sum2 = vpaddlq_u32(sum); const uint64_t sum3 = vgetq_lane_u64(sum2, 0) + vgetq_lane_u64(sum2, 1); return (int)sum3; @@ -767,18 +773,18 @@ static int SSE16x16_NEON(const uint8_t* a, const uint8_t* b) { uint32x4_t sum = vdupq_n_u32(0); int y; for (y = 0; y < 16; ++y) { - AccumulateSSE16(a + y * BPS, b + y * BPS, &sum); + AccumulateSSE16_NEON(a + y * BPS, b + y * BPS, &sum); } - return SumToInt(sum); + return SumToInt_NEON(sum); } static int SSE16x8_NEON(const uint8_t* a, const uint8_t* b) { uint32x4_t sum = vdupq_n_u32(0); int y; for (y = 0; y < 8; ++y) { - AccumulateSSE16(a + y * BPS, b + y * BPS, &sum); + AccumulateSSE16_NEON(a + y * BPS, b + y * BPS, &sum); } - return SumToInt(sum); + return SumToInt_NEON(sum); } static int SSE8x8_NEON(const uint8_t* a, const uint8_t* b) { @@ -791,12 +797,12 @@ static int SSE8x8_NEON(const uint8_t* a, const uint8_t* b) { const uint16x8_t prod = vmull_u8(abs_diff, abs_diff); sum = vpadalq_u16(sum, prod); } - return SumToInt(sum); + return SumToInt_NEON(sum); } static int SSE4x4_NEON(const uint8_t* a, const uint8_t* b) { - const uint8x16_t a0 = Load4x4(a); - const uint8x16_t b0 = Load4x4(b); + const uint8x16_t a0 = Load4x4_NEON(a); + const uint8x16_t b0 = Load4x4_NEON(b); const uint8x16_t abs_diff = vabdq_u8(a0, b0); const uint16x8_t prod1 = vmull_u8(vget_low_u8(abs_diff), vget_low_u8(abs_diff)); @@ -805,7 +811,7 @@ static int SSE4x4_NEON(const uint8_t* a, const uint8_t* b) { /* pair-wise adds and widen */ const uint32x4_t sum1 = vpaddlq_u16(prod1); const uint32x4_t sum2 = vpaddlq_u16(prod2); - return SumToInt(vaddq_u32(sum1, sum2)); + return SumToInt_NEON(vaddq_u32(sum1, sum2)); } //------------------------------------------------------------------------------ @@ -813,8 +819,8 @@ static int SSE4x4_NEON(const uint8_t* a, const uint8_t* b) { // Compilation with gcc-4.6.x is problematic for now. #if !defined(WORK_AROUND_GCC) -static int16x8_t Quantize(int16_t* const in, - const VP8Matrix* const mtx, int offset) { +static int16x8_t Quantize_NEON(int16_t* const in, + const VP8Matrix* const mtx, int offset) { const uint16x8_t sharp = vld1q_u16(&mtx->sharpen_[offset]); const uint16x8_t q = vld1q_u16(&mtx->q_[offset]); const uint16x8_t iq = vld1q_u16(&mtx->iq_[offset]); @@ -847,10 +853,10 @@ static const uint8_t kShuffles[4][8] = { { 14, 15, 22, 23, 28, 29, 30, 31 } }; -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - const int16x8_t out0 = Quantize(in, mtx, 0); - const int16x8_t out1 = Quantize(in, mtx, 8); +static int QuantizeBlock_NEON(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + const int16x8_t out0 = Quantize_NEON(in, mtx, 0); + const int16x8_t out1 = Quantize_NEON(in, mtx, 8); uint8x8x4_t shuffles; // vtbl?_u8 are marked unavailable for iOS arm64 with Xcode < 6.3, use // non-standard versions there. @@ -889,11 +895,11 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16], return 0; } -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { +static int Quantize2Blocks_NEON(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { int nz; - nz = QuantizeBlock(in + 0 * 16, out + 0 * 16, mtx) << 0; - nz |= QuantizeBlock(in + 1 * 16, out + 1 * 16, mtx) << 1; + nz = QuantizeBlock_NEON(in + 0 * 16, out + 0 * 16, mtx) << 0; + nz |= QuantizeBlock_NEON(in + 1 * 16, out + 1 * 16, mtx) << 1; return nz; } @@ -905,14 +911,14 @@ static int Quantize2Blocks(int16_t in[32], int16_t out[32], extern void VP8EncDspInitNEON(void); WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitNEON(void) { - VP8ITransform = ITransform; - VP8FTransform = FTransform; + VP8ITransform = ITransform_NEON; + VP8FTransform = FTransform_NEON; - VP8FTransformWHT = FTransformWHT; + VP8FTransformWHT = FTransformWHT_NEON; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; - VP8CollectHistogram = CollectHistogram; + VP8TDisto4x4 = Disto4x4_NEON; + VP8TDisto16x16 = Disto16x16_NEON; + VP8CollectHistogram = CollectHistogram_NEON; VP8SSE16x16 = SSE16x16_NEON; VP8SSE16x8 = SSE16x8_NEON; @@ -920,8 +926,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitNEON(void) { VP8SSE4x4 = SSE4x4_NEON; #if !defined(WORK_AROUND_GCC) - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; + VP8EncQuantizeBlock = QuantizeBlock_NEON; + VP8EncQuantize2Blocks = Quantize2Blocks_NEON; #endif } diff --git a/3rdparty/libwebp/dsp/enc_sse2.c b/3rdparty/libwebp/src/dsp/enc_sse2.c similarity index 78% rename from 3rdparty/libwebp/dsp/enc_sse2.c rename to 3rdparty/libwebp/src/dsp/enc_sse2.c index 2026a74c91..7b3f142c31 100644 --- a/3rdparty/libwebp/dsp/enc_sse2.c +++ b/3rdparty/libwebp/src/dsp/enc_sse2.c @@ -11,23 +11,23 @@ // // Author: Christian Duvivier (cduvivier@google.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE2) #include #include // for abs() #include -#include "./common_sse2.h" -#include "../enc/cost_enc.h" -#include "../enc/vp8i_enc.h" +#include "src/dsp/common_sse2.h" +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" //------------------------------------------------------------------------------ // Transforms (Paragraph 14.4) // Does one or two inverse transforms. -static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, - int do_two) { +static void ITransform_SSE2(const uint8_t* ref, const int16_t* in, uint8_t* dst, + int do_two) { // This implementation makes use of 16-bit fixed point versions of two // multiply constants: // K1 = sqrt(2) * cos (pi/8) ~= 85627 / 2^16 @@ -193,10 +193,10 @@ static void ITransform(const uint8_t* ref, const int16_t* in, uint8_t* dst, } } -static void FTransformPass1(const __m128i* const in01, - const __m128i* const in23, - __m128i* const out01, - __m128i* const out32) { +static void FTransformPass1_SSE2(const __m128i* const in01, + const __m128i* const in23, + __m128i* const out01, + __m128i* const out32) { const __m128i k937 = _mm_set1_epi32(937); const __m128i k1812 = _mm_set1_epi32(1812); @@ -239,8 +239,9 @@ static void FTransformPass1(const __m128i* const in01, *out32 = _mm_shuffle_epi32(v23, _MM_SHUFFLE(1, 0, 3, 2)); // 3 2 3 2 3 2.. } -static void FTransformPass2(const __m128i* const v01, const __m128i* const v32, - int16_t* out) { +static void FTransformPass2_SSE2(const __m128i* const v01, + const __m128i* const v32, + int16_t* out) { const __m128i zero = _mm_setzero_si128(); const __m128i seven = _mm_set1_epi16(7); const __m128i k5352_2217 = _mm_set_epi16(5352, 2217, 5352, 2217, @@ -291,7 +292,8 @@ static void FTransformPass2(const __m128i* const v01, const __m128i* const v32, _mm_storeu_si128((__m128i*)&out[8], d2_f3); } -static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { +static void FTransform_SSE2(const uint8_t* src, const uint8_t* ref, + int16_t* out) { const __m128i zero = _mm_setzero_si128(); // Load src. const __m128i src0 = _mm_loadl_epi64((const __m128i*)&src[0 * BPS]); @@ -328,13 +330,14 @@ static void FTransform(const uint8_t* src, const uint8_t* ref, int16_t* out) { __m128i v01, v32; // First pass - FTransformPass1(&row01, &row23, &v01, &v32); + FTransformPass1_SSE2(&row01, &row23, &v01, &v32); // Second pass - FTransformPass2(&v01, &v32, out); + FTransformPass2_SSE2(&v01, &v32, out); } -static void FTransform2(const uint8_t* src, const uint8_t* ref, int16_t* out) { +static void FTransform2_SSE2(const uint8_t* src, const uint8_t* ref, + int16_t* out) { const __m128i zero = _mm_setzero_si128(); // Load src and convert to 16b. @@ -374,15 +377,15 @@ static void FTransform2(const uint8_t* src, const uint8_t* ref, int16_t* out) { __m128i v01h, v32h; // First pass - FTransformPass1(&shuf01l, &shuf23l, &v01l, &v32l); - FTransformPass1(&shuf01h, &shuf23h, &v01h, &v32h); + FTransformPass1_SSE2(&shuf01l, &shuf23l, &v01l, &v32l); + FTransformPass1_SSE2(&shuf01h, &shuf23h, &v01h, &v32h); // Second pass - FTransformPass2(&v01l, &v32l, out + 0); - FTransformPass2(&v01h, &v32h, out + 16); + FTransformPass2_SSE2(&v01l, &v32l, out + 0); + FTransformPass2_SSE2(&v01h, &v32h, out + 16); } -static void FTransformWHTRow(const int16_t* const in, __m128i* const out) { +static void FTransformWHTRow_SSE2(const int16_t* const in, __m128i* const out) { const __m128i kMult = _mm_set_epi16(-1, 1, -1, 1, 1, 1, 1, 1); const __m128i src0 = _mm_loadl_epi64((__m128i*)&in[0 * 16]); const __m128i src1 = _mm_loadl_epi64((__m128i*)&in[1 * 16]); @@ -398,14 +401,14 @@ static void FTransformWHTRow(const int16_t* const in, __m128i* const out) { *out = _mm_madd_epi16(D, kMult); } -static void FTransformWHT(const int16_t* in, int16_t* out) { +static void FTransformWHT_SSE2(const int16_t* in, int16_t* out) { // Input is 12b signed. __m128i row0, row1, row2, row3; // Rows are 14b signed. - FTransformWHTRow(in + 0 * 64, &row0); - FTransformWHTRow(in + 1 * 64, &row1); - FTransformWHTRow(in + 2 * 64, &row2); - FTransformWHTRow(in + 3 * 64, &row3); + FTransformWHTRow_SSE2(in + 0 * 64, &row0); + FTransformWHTRow_SSE2(in + 1 * 64, &row1); + FTransformWHTRow_SSE2(in + 2 * 64, &row2); + FTransformWHTRow_SSE2(in + 3 * 64, &row3); { // The a* are 15b signed. @@ -431,9 +434,9 @@ static void FTransformWHT(const int16_t* in, int16_t* out) { // Compute susceptibility based on DCT-coeff histograms: // the higher, the "easier" the macroblock is to compress. -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { +static void CollectHistogram_SSE2(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { const __m128i zero = _mm_setzero_si128(); const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); int j; @@ -442,7 +445,7 @@ static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, int16_t out[16]; int k; - FTransform(ref + VP8DspScan[j], pred + VP8DspScan[j], out); + FTransform_SSE2(ref + VP8DspScan[j], pred + VP8DspScan[j], out); // Convert coefficients to bin (within out[]). { @@ -476,7 +479,7 @@ static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, // Intra predictions // helper for chroma-DC predictions -static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) { +static WEBP_INLINE void Put8x8uv_SSE2(uint8_t v, uint8_t* dst) { int j; const __m128i values = _mm_set1_epi8(v); for (j = 0; j < 8; ++j) { @@ -484,7 +487,7 @@ static WEBP_INLINE void Put8x8uv(uint8_t v, uint8_t* dst) { } } -static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) { +static WEBP_INLINE void Put16_SSE2(uint8_t v, uint8_t* dst) { int j; const __m128i values = _mm_set1_epi8(v); for (j = 0; j < 16; ++j) { @@ -492,20 +495,20 @@ static WEBP_INLINE void Put16(uint8_t v, uint8_t* dst) { } } -static WEBP_INLINE void Fill(uint8_t* dst, int value, int size) { +static WEBP_INLINE void Fill_SSE2(uint8_t* dst, int value, int size) { if (size == 4) { int j; for (j = 0; j < 4; ++j) { memset(dst + j * BPS, value, 4); } } else if (size == 8) { - Put8x8uv(value, dst); + Put8x8uv_SSE2(value, dst); } else { - Put16(value, dst); + Put16_SSE2(value, dst); } } -static WEBP_INLINE void VE8uv(uint8_t* dst, const uint8_t* top) { +static WEBP_INLINE void VE8uv_SSE2(uint8_t* dst, const uint8_t* top) { int j; const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); for (j = 0; j < 8; ++j) { @@ -513,7 +516,7 @@ static WEBP_INLINE void VE8uv(uint8_t* dst, const uint8_t* top) { } } -static WEBP_INLINE void VE16(uint8_t* dst, const uint8_t* top) { +static WEBP_INLINE void VE16_SSE2(uint8_t* dst, const uint8_t* top) { const __m128i top_values = _mm_load_si128((const __m128i*)top); int j; for (j = 0; j < 16; ++j) { @@ -521,20 +524,20 @@ static WEBP_INLINE void VE16(uint8_t* dst, const uint8_t* top) { } } -static WEBP_INLINE void VerticalPred(uint8_t* dst, - const uint8_t* top, int size) { +static WEBP_INLINE void VerticalPred_SSE2(uint8_t* dst, + const uint8_t* top, int size) { if (top != NULL) { if (size == 8) { - VE8uv(dst, top); + VE8uv_SSE2(dst, top); } else { - VE16(dst, top); + VE16_SSE2(dst, top); } } else { - Fill(dst, 127, size); + Fill_SSE2(dst, 127, size); } } -static WEBP_INLINE void HE8uv(uint8_t* dst, const uint8_t* left) { +static WEBP_INLINE void HE8uv_SSE2(uint8_t* dst, const uint8_t* left) { int j; for (j = 0; j < 8; ++j) { const __m128i values = _mm_set1_epi8(left[j]); @@ -543,7 +546,7 @@ static WEBP_INLINE void HE8uv(uint8_t* dst, const uint8_t* left) { } } -static WEBP_INLINE void HE16(uint8_t* dst, const uint8_t* left) { +static WEBP_INLINE void HE16_SSE2(uint8_t* dst, const uint8_t* left) { int j; for (j = 0; j < 16; ++j) { const __m128i values = _mm_set1_epi8(left[j]); @@ -552,21 +555,21 @@ static WEBP_INLINE void HE16(uint8_t* dst, const uint8_t* left) { } } -static WEBP_INLINE void HorizontalPred(uint8_t* dst, - const uint8_t* left, int size) { +static WEBP_INLINE void HorizontalPred_SSE2(uint8_t* dst, + const uint8_t* left, int size) { if (left != NULL) { if (size == 8) { - HE8uv(dst, left); + HE8uv_SSE2(dst, left); } else { - HE16(dst, left); + HE16_SSE2(dst, left); } } else { - Fill(dst, 129, size); + Fill_SSE2(dst, 129, size); } } -static WEBP_INLINE void TM(uint8_t* dst, const uint8_t* left, - const uint8_t* top, int size) { +static WEBP_INLINE void TM_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top, int size) { const __m128i zero = _mm_setzero_si128(); int y; if (size == 8) { @@ -593,13 +596,13 @@ static WEBP_INLINE void TM(uint8_t* dst, const uint8_t* left, } } -static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left, - const uint8_t* top, int size) { +static WEBP_INLINE void TrueMotion_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top, int size) { if (left != NULL) { if (top != NULL) { - TM(dst, left, top, size); + TM_SSE2(dst, left, top, size); } else { - HorizontalPred(dst, left, size); + HorizontalPred_SSE2(dst, left, size); } } else { // true motion without left samples (hence: with default 129 value) @@ -607,90 +610,90 @@ static WEBP_INLINE void TrueMotion(uint8_t* dst, const uint8_t* left, // Note that if top samples are not available, the default value is // then 129, and not 127 as in the VerticalPred case. if (top != NULL) { - VerticalPred(dst, top, size); + VerticalPred_SSE2(dst, top, size); } else { - Fill(dst, 129, size); + Fill_SSE2(dst, 129, size); } } } -static WEBP_INLINE void DC8uv(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { +static WEBP_INLINE void DC8uv_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); const __m128i left_values = _mm_loadl_epi64((const __m128i*)left); const __m128i combined = _mm_unpacklo_epi64(top_values, left_values); const int DC = VP8HorizontalAdd8b(&combined) + 8; - Put8x8uv(DC >> 4, dst); + Put8x8uv_SSE2(DC >> 4, dst); } -static WEBP_INLINE void DC8uvNoLeft(uint8_t* dst, const uint8_t* top) { +static WEBP_INLINE void DC8uvNoLeft_SSE2(uint8_t* dst, const uint8_t* top) { const __m128i zero = _mm_setzero_si128(); const __m128i top_values = _mm_loadl_epi64((const __m128i*)top); const __m128i sum = _mm_sad_epu8(top_values, zero); const int DC = _mm_cvtsi128_si32(sum) + 4; - Put8x8uv(DC >> 3, dst); + Put8x8uv_SSE2(DC >> 3, dst); } -static WEBP_INLINE void DC8uvNoTop(uint8_t* dst, const uint8_t* left) { +static WEBP_INLINE void DC8uvNoTop_SSE2(uint8_t* dst, const uint8_t* left) { // 'left' is contiguous so we can reuse the top summation. - DC8uvNoLeft(dst, left); + DC8uvNoLeft_SSE2(dst, left); } -static WEBP_INLINE void DC8uvNoTopLeft(uint8_t* dst) { - Put8x8uv(0x80, dst); +static WEBP_INLINE void DC8uvNoTopLeft_SSE2(uint8_t* dst) { + Put8x8uv_SSE2(0x80, dst); } -static WEBP_INLINE void DC8uvMode(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { +static WEBP_INLINE void DC8uvMode_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { if (top != NULL) { if (left != NULL) { // top and left present - DC8uv(dst, left, top); + DC8uv_SSE2(dst, left, top); } else { // top, but no left - DC8uvNoLeft(dst, top); + DC8uvNoLeft_SSE2(dst, top); } } else if (left != NULL) { // left but no top - DC8uvNoTop(dst, left); + DC8uvNoTop_SSE2(dst, left); } else { // no top, no left, nothing. - DC8uvNoTopLeft(dst); + DC8uvNoTopLeft_SSE2(dst); } } -static WEBP_INLINE void DC16(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { +static WEBP_INLINE void DC16_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { const __m128i top_row = _mm_load_si128((const __m128i*)top); const __m128i left_row = _mm_load_si128((const __m128i*)left); const int DC = VP8HorizontalAdd8b(&top_row) + VP8HorizontalAdd8b(&left_row) + 16; - Put16(DC >> 5, dst); + Put16_SSE2(DC >> 5, dst); } -static WEBP_INLINE void DC16NoLeft(uint8_t* dst, const uint8_t* top) { +static WEBP_INLINE void DC16NoLeft_SSE2(uint8_t* dst, const uint8_t* top) { const __m128i top_row = _mm_load_si128((const __m128i*)top); const int DC = VP8HorizontalAdd8b(&top_row) + 8; - Put16(DC >> 4, dst); + Put16_SSE2(DC >> 4, dst); } -static WEBP_INLINE void DC16NoTop(uint8_t* dst, const uint8_t* left) { +static WEBP_INLINE void DC16NoTop_SSE2(uint8_t* dst, const uint8_t* left) { // 'left' is contiguous so we can reuse the top summation. - DC16NoLeft(dst, left); + DC16NoLeft_SSE2(dst, left); } -static WEBP_INLINE void DC16NoTopLeft(uint8_t* dst) { - Put16(0x80, dst); +static WEBP_INLINE void DC16NoTopLeft_SSE2(uint8_t* dst) { + Put16_SSE2(0x80, dst); } -static WEBP_INLINE void DC16Mode(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { +static WEBP_INLINE void DC16Mode_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { if (top != NULL) { if (left != NULL) { // top and left present - DC16(dst, left, top); + DC16_SSE2(dst, left, top); } else { // top, but no left - DC16NoLeft(dst, top); + DC16NoLeft_SSE2(dst, top); } } else if (left != NULL) { // left but no top - DC16NoTop(dst, left); + DC16NoTop_SSE2(dst, left); } else { // no top, no left, nothing. - DC16NoTopLeft(dst); + DC16NoTopLeft_SSE2(dst); } } @@ -709,7 +712,8 @@ static WEBP_INLINE void DC16Mode(uint8_t* dst, const uint8_t* left, // where: AC = (a + b + 1) >> 1, BC = (b + c + 1) >> 1 // and ab = a ^ b, bc = b ^ c, lsb = (AC^BC)&1 -static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical +static WEBP_INLINE void VE4_SSE2(uint8_t* dst, + const uint8_t* top) { // vertical const __m128i one = _mm_set1_epi8(1); const __m128i ABCDEFGH = _mm_loadl_epi64((__m128i*)(top - 1)); const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); @@ -725,7 +729,8 @@ static WEBP_INLINE void VE4(uint8_t* dst, const uint8_t* top) { // vertical } } -static WEBP_INLINE void HE4(uint8_t* dst, const uint8_t* top) { // horizontal +static WEBP_INLINE void HE4_SSE2(uint8_t* dst, + const uint8_t* top) { // horizontal const int X = top[-1]; const int I = top[-2]; const int J = top[-3]; @@ -737,14 +742,15 @@ static WEBP_INLINE void HE4(uint8_t* dst, const uint8_t* top) { // horizontal WebPUint32ToMem(dst + 3 * BPS, 0x01010101U * AVG3(K, L, L)); } -static WEBP_INLINE void DC4(uint8_t* dst, const uint8_t* top) { +static WEBP_INLINE void DC4_SSE2(uint8_t* dst, const uint8_t* top) { uint32_t dc = 4; int i; for (i = 0; i < 4; ++i) dc += top[i] + top[-5 + i]; - Fill(dst, dc >> 3, 4); + Fill_SSE2(dst, dc >> 3, 4); } -static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) { // Down-Left +static WEBP_INLINE void LD4_SSE2(uint8_t* dst, + const uint8_t* top) { // Down-Left const __m128i one = _mm_set1_epi8(1); const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top); const __m128i BCDEFGH0 = _mm_srli_si128(ABCDEFGH, 1); @@ -760,8 +766,8 @@ static WEBP_INLINE void LD4(uint8_t* dst, const uint8_t* top) { // Down-Left WebPUint32ToMem(dst + 3 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); } -static WEBP_INLINE void VR4(uint8_t* dst, - const uint8_t* top) { // Vertical-Right +static WEBP_INLINE void VR4_SSE2(uint8_t* dst, + const uint8_t* top) { // Vertical-Right const __m128i one = _mm_set1_epi8(1); const int I = top[-2]; const int J = top[-3]; @@ -786,8 +792,8 @@ static WEBP_INLINE void VR4(uint8_t* dst, DST(0, 3) = AVG3(K, J, I); } -static WEBP_INLINE void VL4(uint8_t* dst, - const uint8_t* top) { // Vertical-Left +static WEBP_INLINE void VL4_SSE2(uint8_t* dst, + const uint8_t* top) { // Vertical-Left const __m128i one = _mm_set1_epi8(1); const __m128i ABCDEFGH = _mm_loadl_epi64((const __m128i*)top); const __m128i BCDEFGH_ = _mm_srli_si128(ABCDEFGH, 1); @@ -812,7 +818,8 @@ static WEBP_INLINE void VL4(uint8_t* dst, DST(3, 3) = (extra_out >> 8) & 0xff; } -static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { // Down-right +static WEBP_INLINE void RD4_SSE2(uint8_t* dst, + const uint8_t* top) { // Down-right const __m128i one = _mm_set1_epi8(1); const __m128i LKJIXABC = _mm_loadl_epi64((const __m128i*)(top - 5)); const __m128i LKJIXABCD = _mm_insert_epi16(LKJIXABC, top[3], 4); @@ -828,7 +835,7 @@ static WEBP_INLINE void RD4(uint8_t* dst, const uint8_t* top) { // Down-right WebPUint32ToMem(dst + 0 * BPS, _mm_cvtsi128_si32(_mm_srli_si128(abcdefg, 3))); } -static WEBP_INLINE void HU4(uint8_t* dst, const uint8_t* top) { +static WEBP_INLINE void HU4_SSE2(uint8_t* dst, const uint8_t* top) { const int I = top[-2]; const int J = top[-3]; const int K = top[-4]; @@ -843,7 +850,7 @@ static WEBP_INLINE void HU4(uint8_t* dst, const uint8_t* top) { DST(0, 3) = DST(1, 3) = DST(2, 3) = DST(3, 3) = L; } -static WEBP_INLINE void HD4(uint8_t* dst, const uint8_t* top) { +static WEBP_INLINE void HD4_SSE2(uint8_t* dst, const uint8_t* top) { const int X = top[-1]; const int I = top[-2]; const int J = top[-3]; @@ -866,7 +873,7 @@ static WEBP_INLINE void HD4(uint8_t* dst, const uint8_t* top) { DST(1, 3) = AVG3(L, K, J); } -static WEBP_INLINE void TM4(uint8_t* dst, const uint8_t* top) { +static WEBP_INLINE void TM4_SSE2(uint8_t* dst, const uint8_t* top) { const __m128i zero = _mm_setzero_si128(); const __m128i top_values = _mm_cvtsi32_si128(WebPMemToUint32(top)); const __m128i top_base = _mm_unpacklo_epi8(top_values, zero); @@ -888,55 +895,56 @@ static WEBP_INLINE void TM4(uint8_t* dst, const uint8_t* top) { // Left samples are top[-5 .. -2], top_left is top[-1], top are // located at top[0..3], and top right is top[4..7] -static void Intra4Preds(uint8_t* dst, const uint8_t* top) { - DC4(I4DC4 + dst, top); - TM4(I4TM4 + dst, top); - VE4(I4VE4 + dst, top); - HE4(I4HE4 + dst, top); - RD4(I4RD4 + dst, top); - VR4(I4VR4 + dst, top); - LD4(I4LD4 + dst, top); - VL4(I4VL4 + dst, top); - HD4(I4HD4 + dst, top); - HU4(I4HU4 + dst, top); +static void Intra4Preds_SSE2(uint8_t* dst, const uint8_t* top) { + DC4_SSE2(I4DC4 + dst, top); + TM4_SSE2(I4TM4 + dst, top); + VE4_SSE2(I4VE4 + dst, top); + HE4_SSE2(I4HE4 + dst, top); + RD4_SSE2(I4RD4 + dst, top); + VR4_SSE2(I4VR4 + dst, top); + LD4_SSE2(I4LD4 + dst, top); + VL4_SSE2(I4VL4 + dst, top); + HD4_SSE2(I4HD4 + dst, top); + HU4_SSE2(I4HU4 + dst, top); } //------------------------------------------------------------------------------ // Chroma 8x8 prediction (paragraph 12.2) -static void IntraChromaPreds(uint8_t* dst, const uint8_t* left, - const uint8_t* top) { +static void IntraChromaPreds_SSE2(uint8_t* dst, const uint8_t* left, + const uint8_t* top) { // U block - DC8uvMode(C8DC8 + dst, left, top); - VerticalPred(C8VE8 + dst, top, 8); - HorizontalPred(C8HE8 + dst, left, 8); - TrueMotion(C8TM8 + dst, left, top, 8); + DC8uvMode_SSE2(C8DC8 + dst, left, top); + VerticalPred_SSE2(C8VE8 + dst, top, 8); + HorizontalPred_SSE2(C8HE8 + dst, left, 8); + TrueMotion_SSE2(C8TM8 + dst, left, top, 8); // V block dst += 8; if (top != NULL) top += 8; if (left != NULL) left += 16; - DC8uvMode(C8DC8 + dst, left, top); - VerticalPred(C8VE8 + dst, top, 8); - HorizontalPred(C8HE8 + dst, left, 8); - TrueMotion(C8TM8 + dst, left, top, 8); + DC8uvMode_SSE2(C8DC8 + dst, left, top); + VerticalPred_SSE2(C8VE8 + dst, top, 8); + HorizontalPred_SSE2(C8HE8 + dst, left, 8); + TrueMotion_SSE2(C8TM8 + dst, left, top, 8); } //------------------------------------------------------------------------------ // luma 16x16 prediction (paragraph 12.3) -static void Intra16Preds(uint8_t* dst, - const uint8_t* left, const uint8_t* top) { - DC16Mode(I16DC16 + dst, left, top); - VerticalPred(I16VE16 + dst, top, 16); - HorizontalPred(I16HE16 + dst, left, 16); - TrueMotion(I16TM16 + dst, left, top, 16); +static void Intra16Preds_SSE2(uint8_t* dst, + const uint8_t* left, const uint8_t* top) { + DC16Mode_SSE2(I16DC16 + dst, left, top); + VerticalPred_SSE2(I16VE16 + dst, top, 16); + HorizontalPred_SSE2(I16HE16 + dst, left, 16); + TrueMotion_SSE2(I16TM16 + dst, left, top, 16); } //------------------------------------------------------------------------------ // Metric -static WEBP_INLINE void SubtractAndAccumulate(const __m128i a, const __m128i b, - __m128i* const sum) { +static WEBP_INLINE void SubtractAndAccumulate_SSE2(const __m128i a, + const __m128i b, + __m128i* const sum) { // take abs(a-b) in 8b const __m128i a_b = _mm_subs_epu8(a, b); const __m128i b_a = _mm_subs_epu8(b, a); @@ -951,8 +959,8 @@ static WEBP_INLINE void SubtractAndAccumulate(const __m128i a, const __m128i b, *sum = _mm_add_epi32(sum1, sum2); } -static WEBP_INLINE int SSE_16xN(const uint8_t* a, const uint8_t* b, - int num_pairs) { +static WEBP_INLINE int SSE_16xN_SSE2(const uint8_t* a, const uint8_t* b, + int num_pairs) { __m128i sum = _mm_setzero_si128(); int32_t tmp[4]; int i; @@ -963,8 +971,8 @@ static WEBP_INLINE int SSE_16xN(const uint8_t* a, const uint8_t* b, const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[BPS * 1]); const __m128i b1 = _mm_loadu_si128((const __m128i*)&b[BPS * 1]); __m128i sum1, sum2; - SubtractAndAccumulate(a0, b0, &sum1); - SubtractAndAccumulate(a1, b1, &sum2); + SubtractAndAccumulate_SSE2(a0, b0, &sum1); + SubtractAndAccumulate_SSE2(a1, b1, &sum2); sum = _mm_add_epi32(sum, _mm_add_epi32(sum1, sum2)); a += 2 * BPS; b += 2 * BPS; @@ -973,18 +981,18 @@ static WEBP_INLINE int SSE_16xN(const uint8_t* a, const uint8_t* b, return (tmp[3] + tmp[2] + tmp[1] + tmp[0]); } -static int SSE16x16(const uint8_t* a, const uint8_t* b) { - return SSE_16xN(a, b, 8); +static int SSE16x16_SSE2(const uint8_t* a, const uint8_t* b) { + return SSE_16xN_SSE2(a, b, 8); } -static int SSE16x8(const uint8_t* a, const uint8_t* b) { - return SSE_16xN(a, b, 4); +static int SSE16x8_SSE2(const uint8_t* a, const uint8_t* b) { + return SSE_16xN_SSE2(a, b, 4); } #define LOAD_8x16b(ptr) \ _mm_unpacklo_epi8(_mm_loadl_epi64((const __m128i*)(ptr)), zero) -static int SSE8x8(const uint8_t* a, const uint8_t* b) { +static int SSE8x8_SSE2(const uint8_t* a, const uint8_t* b) { const __m128i zero = _mm_setzero_si128(); int num_pairs = 4; __m128i sum = zero; @@ -1011,7 +1019,7 @@ static int SSE8x8(const uint8_t* a, const uint8_t* b) { } #undef LOAD_8x16b -static int SSE4x4(const uint8_t* a, const uint8_t* b) { +static int SSE4x4_SSE2(const uint8_t* a, const uint8_t* b) { const __m128i zero = _mm_setzero_si128(); // Load values. Note that we read 8 pixels instead of 4, @@ -1048,7 +1056,7 @@ static int SSE4x4(const uint8_t* a, const uint8_t* b) { //------------------------------------------------------------------------------ -static void Mean16x4(const uint8_t* ref, uint32_t dc[4]) { +static void Mean16x4_SSE2(const uint8_t* ref, uint32_t dc[4]) { const __m128i mask = _mm_set1_epi16(0x00ff); const __m128i a0 = _mm_loadu_si128((const __m128i*)&ref[BPS * 0]); const __m128i a1 = _mm_loadu_si128((const __m128i*)&ref[BPS * 1]); @@ -1086,8 +1094,8 @@ static void Mean16x4(const uint8_t* ref, uint32_t dc[4]) { // Hadamard transform // Returns the weighted sum of the absolute value of transformed coefficients. // w[] contains a row-major 4 by 4 symmetric matrix. -static int TTransform(const uint8_t* inA, const uint8_t* inB, - const uint16_t* const w) { +static int TTransform_SSE2(const uint8_t* inA, const uint8_t* inB, + const uint16_t* const w) { int32_t sum[4]; __m128i tmp_0, tmp_1, tmp_2, tmp_3; const __m128i zero = _mm_setzero_si128(); @@ -1187,19 +1195,19 @@ static int TTransform(const uint8_t* inA, const uint8_t* inB, return sum[0] + sum[1] + sum[2] + sum[3]; } -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - const int diff_sum = TTransform(a, b, w); +static int Disto4x4_SSE2(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int diff_sum = TTransform_SSE2(a, b, w); return abs(diff_sum) >> 5; } -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { +static int Disto16x16_SSE2(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { int D = 0; int x, y; for (y = 0; y < 16 * BPS; y += 4 * BPS) { for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); + D += Disto4x4_SSE2(a + x + y, b + x + y, w); } } return D; @@ -1209,9 +1217,9 @@ static int Disto16x16(const uint8_t* const a, const uint8_t* const b, // Quantization // -static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16], - const uint16_t* const sharpen, - const VP8Matrix* const mtx) { +static WEBP_INLINE int DoQuantizeBlock_SSE2(int16_t in[16], int16_t out[16], + const uint16_t* const sharpen, + const VP8Matrix* const mtx) { const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL); const __m128i zero = _mm_setzero_si128(); __m128i coeff0, coeff8; @@ -1321,22 +1329,22 @@ static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16], return (_mm_movemask_epi8(_mm_cmpeq_epi8(packed_out, zero)) != 0xffff); } -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, &mtx->sharpen_[0], mtx); +static int QuantizeBlock_SSE2(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE2(in, out, &mtx->sharpen_[0], mtx); } -static int QuantizeBlockWHT(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, NULL, mtx); +static int QuantizeBlockWHT_SSE2(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE2(in, out, NULL, mtx); } -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { +static int Quantize2Blocks_SSE2(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { int nz; const uint16_t* const sharpen = &mtx->sharpen_[0]; - nz = DoQuantizeBlock(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; - nz |= DoQuantizeBlock(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; + nz = DoQuantizeBlock_SSE2(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; + nz |= DoQuantizeBlock_SSE2(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; return nz; } @@ -1346,139 +1354,28 @@ static int Quantize2Blocks(int16_t in[32], int16_t out[32], extern void VP8EncDspInitSSE2(void); WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE2(void) { - VP8CollectHistogram = CollectHistogram; - VP8EncPredLuma16 = Intra16Preds; - VP8EncPredChroma8 = IntraChromaPreds; - VP8EncPredLuma4 = Intra4Preds; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8EncQuantizeBlockWHT = QuantizeBlockWHT; - VP8ITransform = ITransform; - VP8FTransform = FTransform; - VP8FTransform2 = FTransform2; - VP8FTransformWHT = FTransformWHT; - VP8SSE16x16 = SSE16x16; - VP8SSE16x8 = SSE16x8; - VP8SSE8x8 = SSE8x8; - VP8SSE4x4 = SSE4x4; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; - VP8Mean16x4 = Mean16x4; -} - -//------------------------------------------------------------------------------ -// SSIM / PSNR entry point (TODO(skal): move to its own file later) - -static uint32_t AccumulateSSE_SSE2(const uint8_t* src1, - const uint8_t* src2, int len) { - int i = 0; - uint32_t sse2 = 0; - if (len >= 16) { - const int limit = len - 32; - int32_t tmp[4]; - __m128i sum1; - __m128i sum = _mm_setzero_si128(); - __m128i a0 = _mm_loadu_si128((const __m128i*)&src1[i]); - __m128i b0 = _mm_loadu_si128((const __m128i*)&src2[i]); - i += 16; - while (i <= limit) { - const __m128i a1 = _mm_loadu_si128((const __m128i*)&src1[i]); - const __m128i b1 = _mm_loadu_si128((const __m128i*)&src2[i]); - __m128i sum2; - i += 16; - SubtractAndAccumulate(a0, b0, &sum1); - sum = _mm_add_epi32(sum, sum1); - a0 = _mm_loadu_si128((const __m128i*)&src1[i]); - b0 = _mm_loadu_si128((const __m128i*)&src2[i]); - i += 16; - SubtractAndAccumulate(a1, b1, &sum2); - sum = _mm_add_epi32(sum, sum2); - } - SubtractAndAccumulate(a0, b0, &sum1); - sum = _mm_add_epi32(sum, sum1); - _mm_storeu_si128((__m128i*)tmp, sum); - sse2 += (tmp[3] + tmp[2] + tmp[1] + tmp[0]); - } - - for (; i < len; ++i) { - const int32_t diff = src1[i] - src2[i]; - sse2 += diff * diff; - } - return sse2; -} - -static uint32_t HorizontalAdd16b(const __m128i* const m) { - uint16_t tmp[8]; - const __m128i a = _mm_srli_si128(*m, 8); - const __m128i b = _mm_add_epi16(*m, a); - _mm_storeu_si128((__m128i*)tmp, b); - return (uint32_t)tmp[3] + tmp[2] + tmp[1] + tmp[0]; -} - -static uint32_t HorizontalAdd32b(const __m128i* const m) { - const __m128i a = _mm_srli_si128(*m, 8); - const __m128i b = _mm_add_epi32(*m, a); - const __m128i c = _mm_add_epi32(b, _mm_srli_si128(b, 4)); - return (uint32_t)_mm_cvtsi128_si32(c); -} - -static const uint16_t kWeight[] = { 1, 2, 3, 4, 3, 2, 1, 0 }; - -#define ACCUMULATE_ROW(WEIGHT) do { \ - /* compute row weight (Wx * Wy) */ \ - const __m128i Wy = _mm_set1_epi16((WEIGHT)); \ - const __m128i W = _mm_mullo_epi16(Wx, Wy); \ - /* process 8 bytes at a time (7 bytes, actually) */ \ - const __m128i a0 = _mm_loadl_epi64((const __m128i*)src1); \ - const __m128i b0 = _mm_loadl_epi64((const __m128i*)src2); \ - /* convert to 16b and multiply by weight */ \ - const __m128i a1 = _mm_unpacklo_epi8(a0, zero); \ - const __m128i b1 = _mm_unpacklo_epi8(b0, zero); \ - const __m128i wa1 = _mm_mullo_epi16(a1, W); \ - const __m128i wb1 = _mm_mullo_epi16(b1, W); \ - /* accumulate */ \ - xm = _mm_add_epi16(xm, wa1); \ - ym = _mm_add_epi16(ym, wb1); \ - xxm = _mm_add_epi32(xxm, _mm_madd_epi16(a1, wa1)); \ - xym = _mm_add_epi32(xym, _mm_madd_epi16(a1, wb1)); \ - yym = _mm_add_epi32(yym, _mm_madd_epi16(b1, wb1)); \ - src1 += stride1; \ - src2 += stride2; \ -} while (0) - -static double SSIMGet_SSE2(const uint8_t* src1, int stride1, - const uint8_t* src2, int stride2) { - VP8DistoStats stats; - const __m128i zero = _mm_setzero_si128(); - __m128i xm = zero, ym = zero; // 16b accums - __m128i xxm = zero, yym = zero, xym = zero; // 32b accum - const __m128i Wx = _mm_loadu_si128((const __m128i*)kWeight); - assert(2 * VP8_SSIM_KERNEL + 1 == 7); - ACCUMULATE_ROW(1); - ACCUMULATE_ROW(2); - ACCUMULATE_ROW(3); - ACCUMULATE_ROW(4); - ACCUMULATE_ROW(3); - ACCUMULATE_ROW(2); - ACCUMULATE_ROW(1); - stats.xm = HorizontalAdd16b(&xm); - stats.ym = HorizontalAdd16b(&ym); - stats.xxm = HorizontalAdd32b(&xxm); - stats.xym = HorizontalAdd32b(&xym); - stats.yym = HorizontalAdd32b(&yym); - return VP8SSIMFromStats(&stats); -} - -extern void VP8SSIMDspInitSSE2(void); - -WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInitSSE2(void) { - VP8AccumulateSSE = AccumulateSSE_SSE2; - VP8SSIMGet = SSIMGet_SSE2; + VP8CollectHistogram = CollectHistogram_SSE2; + VP8EncPredLuma16 = Intra16Preds_SSE2; + VP8EncPredChroma8 = IntraChromaPreds_SSE2; + VP8EncPredLuma4 = Intra4Preds_SSE2; + VP8EncQuantizeBlock = QuantizeBlock_SSE2; + VP8EncQuantize2Blocks = Quantize2Blocks_SSE2; + VP8EncQuantizeBlockWHT = QuantizeBlockWHT_SSE2; + VP8ITransform = ITransform_SSE2; + VP8FTransform = FTransform_SSE2; + VP8FTransform2 = FTransform2_SSE2; + VP8FTransformWHT = FTransformWHT_SSE2; + VP8SSE16x16 = SSE16x16_SSE2; + VP8SSE16x8 = SSE16x8_SSE2; + VP8SSE8x8 = SSE8x8_SSE2; + VP8SSE4x4 = SSE4x4_SSE2; + VP8TDisto4x4 = Disto4x4_SSE2; + VP8TDisto16x16 = Disto16x16_SSE2; + VP8Mean16x4 = Mean16x4_SSE2; } #else // !WEBP_USE_SSE2 WEBP_DSP_INIT_STUB(VP8EncDspInitSSE2) -WEBP_DSP_INIT_STUB(VP8SSIMDspInitSSE2) #endif // WEBP_USE_SSE2 diff --git a/3rdparty/libwebp/dsp/enc_sse41.c b/3rdparty/libwebp/src/dsp/enc_sse41.c similarity index 85% rename from 3rdparty/libwebp/dsp/enc_sse41.c rename to 3rdparty/libwebp/src/dsp/enc_sse41.c index e32086d9fd..924035a644 100644 --- a/3rdparty/libwebp/dsp/enc_sse41.c +++ b/3rdparty/libwebp/src/dsp/enc_sse41.c @@ -11,21 +11,21 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE41) #include #include // for abs() -#include "./common_sse2.h" -#include "../enc/vp8i_enc.h" +#include "src/dsp/common_sse2.h" +#include "src/enc/vp8i_enc.h" //------------------------------------------------------------------------------ // Compute susceptibility based on DCT-coeff histograms. -static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, - int start_block, int end_block, - VP8Histogram* const histo) { +static void CollectHistogram_SSE41(const uint8_t* ref, const uint8_t* pred, + int start_block, int end_block, + VP8Histogram* const histo) { const __m128i max_coeff_thresh = _mm_set1_epi16(MAX_COEFF_THRESH); int j; int distribution[MAX_COEFF_THRESH + 1] = { 0 }; @@ -70,8 +70,8 @@ static void CollectHistogram(const uint8_t* ref, const uint8_t* pred, // Hadamard transform // Returns the weighted sum of the absolute value of transformed coefficients. // w[] contains a row-major 4 by 4 symmetric matrix. -static int TTransform(const uint8_t* inA, const uint8_t* inB, - const uint16_t* const w) { +static int TTransform_SSE41(const uint8_t* inA, const uint8_t* inB, + const uint16_t* const w) { int32_t sum[4]; __m128i tmp_0, tmp_1, tmp_2, tmp_3; @@ -168,19 +168,19 @@ static int TTransform(const uint8_t* inA, const uint8_t* inB, return sum[0] + sum[1] + sum[2] + sum[3]; } -static int Disto4x4(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { - const int diff_sum = TTransform(a, b, w); +static int Disto4x4_SSE41(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { + const int diff_sum = TTransform_SSE41(a, b, w); return abs(diff_sum) >> 5; } -static int Disto16x16(const uint8_t* const a, const uint8_t* const b, - const uint16_t* const w) { +static int Disto16x16_SSE41(const uint8_t* const a, const uint8_t* const b, + const uint16_t* const w) { int D = 0; int x, y; for (y = 0; y < 16 * BPS; y += 4 * BPS) { for (x = 0; x < 16; x += 4) { - D += Disto4x4(a + x + y, b + x + y, w); + D += Disto4x4_SSE41(a + x + y, b + x + y, w); } } return D; @@ -197,9 +197,9 @@ static int Disto16x16(const uint8_t* const a, const uint8_t* const b, 2 * (D) + 1, 2 * (D) + 0, 2 * (C) + 1, 2 * (C) + 0, \ 2 * (B) + 1, 2 * (B) + 0, 2 * (A) + 1, 2 * (A) + 0) -static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16], - const uint16_t* const sharpen, - const VP8Matrix* const mtx) { +static WEBP_INLINE int DoQuantizeBlock_SSE41(int16_t in[16], int16_t out[16], + const uint16_t* const sharpen, + const VP8Matrix* const mtx) { const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL); const __m128i zero = _mm_setzero_si128(); __m128i out0, out8; @@ -300,22 +300,22 @@ static WEBP_INLINE int DoQuantizeBlock(int16_t in[16], int16_t out[16], #undef PSHUFB_CST -static int QuantizeBlock(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, &mtx->sharpen_[0], mtx); +static int QuantizeBlock_SSE41(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE41(in, out, &mtx->sharpen_[0], mtx); } -static int QuantizeBlockWHT(int16_t in[16], int16_t out[16], - const VP8Matrix* const mtx) { - return DoQuantizeBlock(in, out, NULL, mtx); +static int QuantizeBlockWHT_SSE41(int16_t in[16], int16_t out[16], + const VP8Matrix* const mtx) { + return DoQuantizeBlock_SSE41(in, out, NULL, mtx); } -static int Quantize2Blocks(int16_t in[32], int16_t out[32], - const VP8Matrix* const mtx) { +static int Quantize2Blocks_SSE41(int16_t in[32], int16_t out[32], + const VP8Matrix* const mtx) { int nz; const uint16_t* const sharpen = &mtx->sharpen_[0]; - nz = DoQuantizeBlock(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; - nz |= DoQuantizeBlock(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; + nz = DoQuantizeBlock_SSE41(in + 0 * 16, out + 0 * 16, sharpen, mtx) << 0; + nz |= DoQuantizeBlock_SSE41(in + 1 * 16, out + 1 * 16, sharpen, mtx) << 1; return nz; } @@ -324,12 +324,12 @@ static int Quantize2Blocks(int16_t in[32], int16_t out[32], extern void VP8EncDspInitSSE41(void); WEBP_TSAN_IGNORE_FUNCTION void VP8EncDspInitSSE41(void) { - VP8CollectHistogram = CollectHistogram; - VP8EncQuantizeBlock = QuantizeBlock; - VP8EncQuantize2Blocks = Quantize2Blocks; - VP8EncQuantizeBlockWHT = QuantizeBlockWHT; - VP8TDisto4x4 = Disto4x4; - VP8TDisto16x16 = Disto16x16; + VP8CollectHistogram = CollectHistogram_SSE41; + VP8EncQuantizeBlock = QuantizeBlock_SSE41; + VP8EncQuantize2Blocks = Quantize2Blocks_SSE41; + VP8EncQuantizeBlockWHT = QuantizeBlockWHT_SSE41; + VP8TDisto4x4 = Disto4x4_SSE41; + VP8TDisto16x16 = Disto16x16_SSE41; } #else // !WEBP_USE_SSE41 diff --git a/3rdparty/libwebp/dsp/filters.c b/3rdparty/libwebp/src/dsp/filters.c similarity index 60% rename from 3rdparty/libwebp/dsp/filters.c rename to 3rdparty/libwebp/src/dsp/filters.c index 65f34aad1f..ca5f877da7 100644 --- a/3rdparty/libwebp/dsp/filters.c +++ b/3rdparty/libwebp/src/dsp/filters.c @@ -11,7 +11,7 @@ // // Author: Urvang (urvang@google.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #include #include #include @@ -20,16 +20,17 @@ // Helpful macro. # define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ + assert((in) != NULL); \ + assert((out) != NULL); \ assert(width > 0); \ assert(height > 0); \ assert(stride >= width); \ assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ (void)height; // Silence unused warning. -static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred, - uint8_t* dst, int length, int inverse) { +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE void PredictLine_C(const uint8_t* src, const uint8_t* pred, + uint8_t* dst, int length, int inverse) { int i; if (inverse) { for (i = 0; i < length; ++i) dst[i] = src[i] + pred[i]; @@ -41,7 +42,44 @@ static WEBP_INLINE void PredictLine(const uint8_t* src, const uint8_t* pred, //------------------------------------------------------------------------------ // Horizontal filter. -static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, +static WEBP_INLINE void DoHorizontalFilter_C(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + int inverse, uint8_t* out) { + const uint8_t* preds; + const size_t start_offset = row * stride; + const int last_row = row + num_rows; + SANITY_CHECK(in, out); + in += start_offset; + out += start_offset; + preds = inverse ? out : in; + + if (row == 0) { + // Leftmost pixel is the same as input for topmost scanline. + out[0] = in[0]; + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); + row = 1; + preds += stride; + in += stride; + out += stride; + } + + // Filter line-by-line. + while (row < last_row) { + // Leftmost pixel is predicted from above. + PredictLine_C(in, preds - stride, out, 1, inverse); + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); + ++row; + preds += stride; + in += stride; + out += stride; + } +} + +//------------------------------------------------------------------------------ +// Vertical filter. + +static WEBP_INLINE void DoVerticalFilter_C(const uint8_t* in, int width, int height, int stride, int row, int num_rows, int inverse, uint8_t* out) { @@ -53,48 +91,11 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, out += start_offset; preds = inverse ? out : in; - if (row == 0) { - // Leftmost pixel is the same as input for topmost scanline. - out[0] = in[0]; - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - row = 1; - preds += stride; - in += stride; - out += stride; - } - - // Filter line-by-line. - while (row < last_row) { - // Leftmost pixel is predicted from above. - PredictLine(in, preds - stride, out, 1, inverse); - PredictLine(in + 1, preds, out + 1, width - 1, inverse); - ++row; - preds += stride; - in += stride; - out += stride; - } -} - -//------------------------------------------------------------------------------ -// Vertical filter. - -static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { - const uint8_t* preds; - const size_t start_offset = row * stride; - const int last_row = row + num_rows; - SANITY_CHECK(in, out); - in += start_offset; - out += start_offset; - preds = inverse ? out : in; - if (row == 0) { // Very first top-left pixel is copied. out[0] = in[0]; // Rest of top scan-line is left-predicted. - PredictLine(in + 1, preds, out + 1, width - 1, inverse); + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); row = 1; in += stride; out += stride; @@ -105,26 +106,28 @@ static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, // Filter line-by-line. while (row < last_row) { - PredictLine(in, preds, out, width, inverse); + PredictLine_C(in, preds, out, width, inverse); ++row; preds += stride; in += stride; out += stride; } } +#endif // !WEBP_NEON_OMIT_C_CODE //------------------------------------------------------------------------------ // Gradient filter. -static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { +static WEBP_INLINE int GradientPredictor_C(uint8_t a, uint8_t b, uint8_t c) { const int g = a + b - c; return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit } -static WEBP_INLINE void DoGradientFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - int inverse, uint8_t* out) { +#if !WEBP_NEON_OMIT_C_CODE +static WEBP_INLINE void DoGradientFilter_C(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + int inverse, uint8_t* out) { const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; @@ -136,7 +139,7 @@ static WEBP_INLINE void DoGradientFilter(const uint8_t* in, // left prediction for top scan-line if (row == 0) { out[0] = in[0]; - PredictLine(in + 1, preds, out + 1, width - 1, inverse); + PredictLine_C(in + 1, preds, out + 1, width - 1, inverse); row = 1; preds += stride; in += stride; @@ -147,11 +150,11 @@ static WEBP_INLINE void DoGradientFilter(const uint8_t* in, while (row < last_row) { int w; // leftmost pixel: predict from above. - PredictLine(in, preds - stride, out, 1, inverse); + PredictLine_C(in, preds - stride, out, 1, inverse); for (w = 1; w < width; ++w) { - const int pred = GradientPredictor(preds[w - 1], - preds[w - stride], - preds[w - stride - 1]); + const int pred = GradientPredictor_C(preds[w - 1], + preds[w - stride], + preds[w - stride - 1]); out[w] = in[w] + (inverse ? pred : -pred); } ++row; @@ -160,32 +163,34 @@ static WEBP_INLINE void DoGradientFilter(const uint8_t* in, out += stride; } } +#endif // !WEBP_NEON_OMIT_C_CODE #undef SANITY_CHECK //------------------------------------------------------------------------------ -static void HorizontalFilter(const uint8_t* data, int width, int height, +#if !WEBP_NEON_OMIT_C_CODE +static void HorizontalFilter_C(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoHorizontalFilter_C(data, width, height, stride, 0, height, 0, + filtered_data); +} + +static void VerticalFilter_C(const uint8_t* data, int width, int height, int stride, uint8_t* filtered_data) { - DoHorizontalFilter(data, width, height, stride, 0, height, 0, filtered_data); + DoVerticalFilter_C(data, width, height, stride, 0, height, 0, filtered_data); } -static void VerticalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoVerticalFilter(data, width, height, stride, 0, height, 0, filtered_data); +static void GradientFilter_C(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoGradientFilter_C(data, width, height, stride, 0, height, 0, filtered_data); } - - -static void GradientFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoGradientFilter(data, width, height, stride, 0, height, 0, filtered_data); -} - +#endif // !WEBP_NEON_OMIT_C_CODE //------------------------------------------------------------------------------ -static void HorizontalUnfilter(const uint8_t* prev, const uint8_t* in, - uint8_t* out, int width) { +static void HorizontalUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { uint8_t pred = (prev == NULL) ? 0 : prev[0]; int i; for (i = 0; i < width; ++i) { @@ -194,26 +199,28 @@ static void HorizontalUnfilter(const uint8_t* prev, const uint8_t* in, } } -static void VerticalUnfilter(const uint8_t* prev, const uint8_t* in, - uint8_t* out, int width) { +#if !WEBP_NEON_OMIT_C_CODE +static void VerticalUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { if (prev == NULL) { - HorizontalUnfilter(NULL, in, out, width); + HorizontalUnfilter_C(NULL, in, out, width); } else { int i; for (i = 0; i < width; ++i) out[i] = prev[i] + in[i]; } } +#endif // !WEBP_NEON_OMIT_C_CODE -static void GradientUnfilter(const uint8_t* prev, const uint8_t* in, - uint8_t* out, int width) { +static void GradientUnfilter_C(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { if (prev == NULL) { - HorizontalUnfilter(NULL, in, out, width); + HorizontalUnfilter_C(NULL, in, out, width); } else { uint8_t top = prev[0], top_left = top, left = top; int i; for (i = 0; i < width; ++i) { top = prev[i]; // need to read this first, in case prev==out - left = in[i] + GradientPredictor(left, top, top_left); + left = in[i] + GradientPredictor_C(left, top, top_left); top_left = top; out[i] = left; } @@ -238,14 +245,18 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) { if (filters_last_cpuinfo_used == VP8GetCPUInfo) return; WebPUnfilters[WEBP_FILTER_NONE] = NULL; - WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter; - WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter; - WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter; +#if !WEBP_NEON_OMIT_C_CODE + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_C; + WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_C; +#endif + WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_C; WebPFilters[WEBP_FILTER_NONE] = NULL; - WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; - WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; - WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; +#if !WEBP_NEON_OMIT_C_CODE + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_C; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_C; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_C; +#endif if (VP8GetCPUInfo != NULL) { #if defined(WEBP_USE_SSE2) @@ -253,11 +264,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) { VP8FiltersInitSSE2(); } #endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8FiltersInitNEON(); - } -#endif #if defined(WEBP_USE_MIPS_DSP_R2) if (VP8GetCPUInfo(kMIPSdspR2)) { VP8FiltersInitMIPSdspR2(); @@ -269,5 +275,20 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInit(void) { } #endif } + +#if defined(WEBP_USE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8FiltersInitNEON(); + } +#endif + + assert(WebPUnfilters[WEBP_FILTER_HORIZONTAL] != NULL); + assert(WebPUnfilters[WEBP_FILTER_VERTICAL] != NULL); + assert(WebPUnfilters[WEBP_FILTER_GRADIENT] != NULL); + assert(WebPFilters[WEBP_FILTER_HORIZONTAL] != NULL); + assert(WebPFilters[WEBP_FILTER_VERTICAL] != NULL); + assert(WebPFilters[WEBP_FILTER_GRADIENT] != NULL); + filters_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/3rdparty/libwebp/dsp/filters_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/filters_mips_dsp_r2.c similarity index 83% rename from 3rdparty/libwebp/dsp/filters_mips_dsp_r2.c rename to 3rdparty/libwebp/src/dsp/filters_mips_dsp_r2.c index 1d82e3c2e1..9382b12823 100644 --- a/3rdparty/libwebp/dsp/filters_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/filters_mips_dsp_r2.c @@ -12,11 +12,11 @@ // Author(s): Branimir Vasic (branimir.vasic@imgtec.com) // Djordje Pesut (djordje.pesut@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS_DSP_R2) -#include "../dsp/dsp.h" +#include "src/dsp/dsp.h" #include #include #include @@ -101,8 +101,8 @@ ); \ } while (0) -static WEBP_INLINE void PredictLine(const uint8_t* src, uint8_t* dst, - int length) { +static WEBP_INLINE void PredictLine_MIPSdspR2(const uint8_t* src, uint8_t* dst, + int length) { DO_PREDICT_LINE(src, dst, length, 0); } @@ -192,10 +192,11 @@ static WEBP_INLINE void PredictLine(const uint8_t* src, uint8_t* dst, } \ } while (0) -static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - uint8_t* out) { +static WEBP_INLINE void DoHorizontalFilter_MIPSdspR2(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; @@ -207,7 +208,7 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, if (row == 0) { // Leftmost pixel is the same as input for topmost scanline. out[0] = in[0]; - PredictLine(in + 1, out + 1, width - 1); + PredictLine_MIPSdspR2(in + 1, out + 1, width - 1); row = 1; preds += stride; in += stride; @@ -219,9 +220,11 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, } #undef FILTER_LINE_BY_LINE -static void HorizontalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoHorizontalFilter(data, width, height, stride, 0, height, filtered_data); +static void HorizontalFilter_MIPSdspR2(const uint8_t* data, + int width, int height, + int stride, uint8_t* filtered_data) { + DoHorizontalFilter_MIPSdspR2(data, width, height, stride, 0, height, + filtered_data); } //------------------------------------------------------------------------------ @@ -237,9 +240,11 @@ static void HorizontalFilter(const uint8_t* data, int width, int height, } \ } while (0) -static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, uint8_t* out) { +static WEBP_INLINE void DoVerticalFilter_MIPSdspR2(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; @@ -252,7 +257,7 @@ static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, // Very first top-left pixel is copied. out[0] = in[0]; // Rest of top scan-line is left-predicted. - PredictLine(in + 1, out + 1, width - 1); + PredictLine_MIPSdspR2(in + 1, out + 1, width - 1); row = 1; in += stride; out += stride; @@ -266,15 +271,16 @@ static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, } #undef FILTER_LINE_BY_LINE -static void VerticalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoVerticalFilter(data, width, height, stride, 0, height, filtered_data); +static void VerticalFilter_MIPSdspR2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoVerticalFilter_MIPSdspR2(data, width, height, stride, 0, height, + filtered_data); } //------------------------------------------------------------------------------ // Gradient filter. -static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { +static int GradientPredictor_MIPSdspR2(uint8_t a, uint8_t b, uint8_t c) { int temp0; __asm__ volatile ( "addu %[temp0], %[a], %[b] \n\t" @@ -293,9 +299,9 @@ static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { int w; \ PREDICT_LINE_ONE_PASS(in, PREDS - stride, out); \ for (w = 1; w < width; ++w) { \ - const int pred = GradientPredictor(PREDS[w - 1], \ - PREDS[w - stride], \ - PREDS[w - stride - 1]); \ + const int pred = GradientPredictor_MIPSdspR2(PREDS[w - 1], \ + PREDS[w - stride], \ + PREDS[w - stride - 1]); \ out[w] = in[w] OPERATION pred; \ } \ ++row; \ @@ -304,9 +310,9 @@ static WEBP_INLINE int GradientPredictor(uint8_t a, uint8_t b, uint8_t c) { } \ } while (0) -static WEBP_INLINE void DoGradientFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, uint8_t* out) { +static void DoGradientFilter_MIPSdspR2(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, uint8_t* out) { const uint8_t* preds; const size_t start_offset = row * stride; const int last_row = row + num_rows; @@ -318,7 +324,7 @@ static WEBP_INLINE void DoGradientFilter(const uint8_t* in, // left prediction for top scan-line if (row == 0) { out[0] = in[0]; - PredictLine(in + 1, out + 1, width - 1); + PredictLine_MIPSdspR2(in + 1, out + 1, width - 1); row = 1; preds += stride; in += stride; @@ -330,38 +336,39 @@ static WEBP_INLINE void DoGradientFilter(const uint8_t* in, } #undef FILTER_LINE_BY_LINE -static void GradientFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoGradientFilter(data, width, height, stride, 0, height, filtered_data); +static void GradientFilter_MIPSdspR2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoGradientFilter_MIPSdspR2(data, width, height, stride, 0, height, + filtered_data); } //------------------------------------------------------------------------------ -static void HorizontalUnfilter(const uint8_t* prev, const uint8_t* in, - uint8_t* out, int width) { +static void HorizontalUnfilter_MIPSdspR2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { out[0] = in[0] + (prev == NULL ? 0 : prev[0]); DO_PREDICT_LINE(in + 1, out + 1, width - 1, 1); } -static void VerticalUnfilter(const uint8_t* prev, const uint8_t* in, - uint8_t* out, int width) { +static void VerticalUnfilter_MIPSdspR2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { if (prev == NULL) { - HorizontalUnfilter(NULL, in, out, width); + HorizontalUnfilter_MIPSdspR2(NULL, in, out, width); } else { DO_PREDICT_LINE_VERTICAL(in, prev, out, width, 1); } } -static void GradientUnfilter(const uint8_t* prev, const uint8_t* in, - uint8_t* out, int width) { +static void GradientUnfilter_MIPSdspR2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { if (prev == NULL) { - HorizontalUnfilter(NULL, in, out, width); + HorizontalUnfilter_MIPSdspR2(NULL, in, out, width); } else { uint8_t top = prev[0], top_left = top, left = top; int i; for (i = 0; i < width; ++i) { top = prev[i]; // need to read this first, in case prev==dst - left = in[i] + GradientPredictor(left, top, top_left); + left = in[i] + GradientPredictor_MIPSdspR2(left, top, top_left); top_left = top; out[i] = left; } @@ -379,13 +386,13 @@ static void GradientUnfilter(const uint8_t* prev, const uint8_t* in, extern void VP8FiltersInitMIPSdspR2(void); WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMIPSdspR2(void) { - WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter; - WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter; - WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter; + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_MIPSdspR2; + WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_MIPSdspR2; + WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_MIPSdspR2; - WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; - WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; - WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_MIPSdspR2; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_MIPSdspR2; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_MIPSdspR2; } #else // !WEBP_USE_MIPS_DSP_R2 diff --git a/3rdparty/libwebp/dsp/filters_msa.c b/3rdparty/libwebp/src/dsp/filters_msa.c similarity index 88% rename from 3rdparty/libwebp/dsp/filters_msa.c rename to 3rdparty/libwebp/src/dsp/filters_msa.c index 4b8922d0bc..14c437d141 100644 --- a/3rdparty/libwebp/dsp/filters_msa.c +++ b/3rdparty/libwebp/src/dsp/filters_msa.c @@ -11,11 +11,11 @@ // // Author: Prashant Patil (prashant.patil@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MSA) -#include "./msa_macro.h" +#include "src/dsp/msa_macro.h" #include @@ -66,8 +66,8 @@ static WEBP_INLINE void PredictLineInverse0(const uint8_t* src, //------------------------------------------------------------------------------ // Horrizontal filter -static void HorizontalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { +static void HorizontalFilter_MSA(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { const uint8_t* preds = data; const uint8_t* in = data; uint8_t* out = filtered_data; @@ -129,8 +129,8 @@ static WEBP_INLINE void PredictLineGradient(const uint8_t* pinput, } -static void GradientFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { +static void GradientFilter_MSA(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { const uint8_t* in = data; const uint8_t* preds = data; uint8_t* out = filtered_data; @@ -157,8 +157,8 @@ static void GradientFilter(const uint8_t* data, int width, int height, //------------------------------------------------------------------------------ // Vertical filter -static void VerticalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { +static void VerticalFilter_MSA(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { const uint8_t* in = data; const uint8_t* preds = data; uint8_t* out = filtered_data; @@ -190,9 +190,9 @@ static void VerticalFilter(const uint8_t* data, int width, int height, extern void VP8FiltersInitMSA(void); WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitMSA(void) { - WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; - WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; - WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_MSA; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_MSA; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_MSA; } #else // !WEBP_USE_MSA diff --git a/3rdparty/libwebp/dsp/filters_neon.c b/3rdparty/libwebp/src/dsp/filters_neon.c similarity index 96% rename from 3rdparty/libwebp/dsp/filters_neon.c rename to 3rdparty/libwebp/src/dsp/filters_neon.c index 4d6e50cc76..3e6a578ea7 100644 --- a/3rdparty/libwebp/dsp/filters_neon.c +++ b/3rdparty/libwebp/src/dsp/filters_neon.c @@ -11,12 +11,12 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_NEON) #include -#include "./neon.h" +#include "src/dsp/neon.h" //------------------------------------------------------------------------------ // Helpful macros. @@ -134,7 +134,7 @@ static WEBP_INLINE void DoVerticalFilter_NEON(const uint8_t* in, } static void VerticalFilter_NEON(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { + int stride, uint8_t* filtered_data) { DoVerticalFilter_NEON(data, width, height, stride, 0, height, filtered_data); } @@ -196,7 +196,7 @@ static WEBP_INLINE void DoGradientFilter_NEON(const uint8_t* in, } static void GradientFilter_NEON(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { + int stride, uint8_t* filtered_data) { DoGradientFilter_NEON(data, width, height, stride, 0, height, filtered_data); } @@ -251,9 +251,11 @@ static void VerticalUnfilter_NEON(const uint8_t* prev, const uint8_t* in, // GradientUnfilter_NEON is correct but slower than the C-version, // at least on ARM64. For armv7, it's a wash. // So best is to disable it for now, but keep the idea around... -// #define USE_GRADIENT_UNFILTER +#if !defined(USE_GRADIENT_UNFILTER) +#define USE_GRADIENT_UNFILTER 0 // ALTERNATE_CODE +#endif -#if defined(USE_GRADIENT_UNFILTER) +#if (USE_GRADIENT_UNFILTER == 1) #define GRAD_PROCESS_LANE(L) do { \ const uint8x8_t tmp1 = ROTATE_RIGHT_N(pred, 1); /* rotate predictor in */ \ const int16x8_t tmp2 = vaddq_s16(BC, U8_TO_S16(tmp1)); \ @@ -292,7 +294,7 @@ static void GradientPredictInverse_NEON(const uint8_t* const in, #undef GRAD_PROCESS_LANE static void GradientUnfilter_NEON(const uint8_t* prev, const uint8_t* in, - uint8_t* out, int width) { + uint8_t* out, int width) { if (prev == NULL) { HorizontalUnfilter_NEON(NULL, in, out, width); } else { @@ -311,7 +313,7 @@ extern void VP8FiltersInitNEON(void); WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitNEON(void) { WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_NEON; WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_NEON; -#if defined(USE_GRADIENT_UNFILTER) +#if (USE_GRADIENT_UNFILTER == 1) WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_NEON; #endif diff --git a/3rdparty/libwebp/dsp/filters_sse2.c b/3rdparty/libwebp/src/dsp/filters_sse2.c similarity index 69% rename from 3rdparty/libwebp/dsp/filters_sse2.c rename to 3rdparty/libwebp/src/dsp/filters_sse2.c index 67f77999e6..5a18895676 100644 --- a/3rdparty/libwebp/dsp/filters_sse2.c +++ b/3rdparty/libwebp/src/dsp/filters_sse2.c @@ -11,7 +11,7 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE2) @@ -24,16 +24,16 @@ // Helpful macro. # define SANITY_CHECK(in, out) \ - assert(in != NULL); \ - assert(out != NULL); \ + assert((in) != NULL); \ + assert((out) != NULL); \ assert(width > 0); \ assert(height > 0); \ assert(stride >= width); \ assert(row >= 0 && num_rows > 0 && row + num_rows <= height); \ (void)height; // Silence unused warning. -static void PredictLineTop(const uint8_t* src, const uint8_t* pred, - uint8_t* dst, int length) { +static void PredictLineTop_SSE2(const uint8_t* src, const uint8_t* pred, + uint8_t* dst, int length) { int i; const int max_pos = length & ~31; assert(length >= 0); @@ -51,7 +51,7 @@ static void PredictLineTop(const uint8_t* src, const uint8_t* pred, } // Special case for left-based prediction (when preds==dst-1 or preds==src-1). -static void PredictLineLeft(const uint8_t* src, uint8_t* dst, int length) { +static void PredictLineLeft_SSE2(const uint8_t* src, uint8_t* dst, int length) { int i; const int max_pos = length & ~31; assert(length >= 0); @@ -71,10 +71,11 @@ static void PredictLineLeft(const uint8_t* src, uint8_t* dst, int length) { //------------------------------------------------------------------------------ // Horizontal filter. -static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - uint8_t* out) { +static WEBP_INLINE void DoHorizontalFilter_SSE2(const uint8_t* in, + int width, int height, + int stride, + int row, int num_rows, + uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; SANITY_CHECK(in, out); @@ -84,7 +85,7 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, if (row == 0) { // Leftmost pixel is the same as input for topmost scanline. out[0] = in[0]; - PredictLineLeft(in + 1, out + 1, width - 1); + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); row = 1; in += stride; out += stride; @@ -94,7 +95,7 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, while (row < last_row) { // Leftmost pixel is predicted from above. out[0] = in[0] - in[-stride]; - PredictLineLeft(in + 1, out + 1, width - 1); + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); ++row; in += stride; out += stride; @@ -104,9 +105,10 @@ static WEBP_INLINE void DoHorizontalFilter(const uint8_t* in, //------------------------------------------------------------------------------ // Vertical filter. -static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, uint8_t* out) { +static WEBP_INLINE void DoVerticalFilter_SSE2(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; SANITY_CHECK(in, out); @@ -117,7 +119,7 @@ static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, // Very first top-left pixel is copied. out[0] = in[0]; // Rest of top scan-line is left-predicted. - PredictLineLeft(in + 1, out + 1, width - 1); + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); row = 1; in += stride; out += stride; @@ -125,7 +127,7 @@ static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, // Filter line-by-line. while (row < last_row) { - PredictLineTop(in, in - stride, out, width); + PredictLineTop_SSE2(in, in - stride, out, width); ++row; in += stride; out += stride; @@ -135,14 +137,14 @@ static WEBP_INLINE void DoVerticalFilter(const uint8_t* in, //------------------------------------------------------------------------------ // Gradient filter. -static WEBP_INLINE int GradientPredictorC(uint8_t a, uint8_t b, uint8_t c) { +static WEBP_INLINE int GradientPredictor_SSE2(uint8_t a, uint8_t b, uint8_t c) { const int g = a + b - c; return ((g & ~0xff) == 0) ? g : (g < 0) ? 0 : 255; // clip to 8bit } -static void GradientPredictDirect(const uint8_t* const row, - const uint8_t* const top, - uint8_t* const out, int length) { +static void GradientPredictDirect_SSE2(const uint8_t* const row, + const uint8_t* const top, + uint8_t* const out, int length) { const int max_pos = length & ~7; int i; const __m128i zero = _mm_setzero_si128(); @@ -161,14 +163,14 @@ static void GradientPredictDirect(const uint8_t* const row, _mm_storel_epi64((__m128i*)(out + i), H); } for (; i < length; ++i) { - out[i] = row[i] - GradientPredictorC(row[i - 1], top[i], top[i - 1]); + out[i] = row[i] - GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]); } } -static WEBP_INLINE void DoGradientFilter(const uint8_t* in, - int width, int height, int stride, - int row, int num_rows, - uint8_t* out) { +static WEBP_INLINE void DoGradientFilter_SSE2(const uint8_t* in, + int width, int height, int stride, + int row, int num_rows, + uint8_t* out) { const size_t start_offset = row * stride; const int last_row = row + num_rows; SANITY_CHECK(in, out); @@ -178,7 +180,7 @@ static WEBP_INLINE void DoGradientFilter(const uint8_t* in, // left prediction for top scan-line if (row == 0) { out[0] = in[0]; - PredictLineLeft(in + 1, out + 1, width - 1); + PredictLineLeft_SSE2(in + 1, out + 1, width - 1); row = 1; in += stride; out += stride; @@ -187,7 +189,7 @@ static WEBP_INLINE void DoGradientFilter(const uint8_t* in, // Filter line-by-line. while (row < last_row) { out[0] = in[0] - in[-stride]; - GradientPredictDirect(in + 1, in + 1 - stride, out + 1, width - 1); + GradientPredictDirect_SSE2(in + 1, in + 1 - stride, out + 1, width - 1); ++row; in += stride; out += stride; @@ -198,26 +200,27 @@ static WEBP_INLINE void DoGradientFilter(const uint8_t* in, //------------------------------------------------------------------------------ -static void HorizontalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoHorizontalFilter(data, width, height, stride, 0, height, filtered_data); +static void HorizontalFilter_SSE2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoHorizontalFilter_SSE2(data, width, height, stride, 0, height, + filtered_data); } -static void VerticalFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoVerticalFilter(data, width, height, stride, 0, height, filtered_data); +static void VerticalFilter_SSE2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoVerticalFilter_SSE2(data, width, height, stride, 0, height, filtered_data); } -static void GradientFilter(const uint8_t* data, int width, int height, - int stride, uint8_t* filtered_data) { - DoGradientFilter(data, width, height, stride, 0, height, filtered_data); +static void GradientFilter_SSE2(const uint8_t* data, int width, int height, + int stride, uint8_t* filtered_data) { + DoGradientFilter_SSE2(data, width, height, stride, 0, height, filtered_data); } //------------------------------------------------------------------------------ // Inverse transforms -static void HorizontalUnfilter(const uint8_t* prev, const uint8_t* in, - uint8_t* out, int width) { +static void HorizontalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { int i; __m128i last; out[0] = in[0] + (prev == NULL ? 0 : prev[0]); @@ -238,10 +241,10 @@ static void HorizontalUnfilter(const uint8_t* prev, const uint8_t* in, for (; i < width; ++i) out[i] = in[i] + out[i - 1]; } -static void VerticalUnfilter(const uint8_t* prev, const uint8_t* in, - uint8_t* out, int width) { +static void VerticalUnfilter_SSE2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { if (prev == NULL) { - HorizontalUnfilter(NULL, in, out, width); + HorizontalUnfilter_SSE2(NULL, in, out, width); } else { int i; const int max_pos = width & ~31; @@ -260,9 +263,9 @@ static void VerticalUnfilter(const uint8_t* prev, const uint8_t* in, } } -static void GradientPredictInverse(const uint8_t* const in, - const uint8_t* const top, - uint8_t* const row, int length) { +static void GradientPredictInverse_SSE2(const uint8_t* const in, + const uint8_t* const top, + uint8_t* const row, int length) { if (length > 0) { int i; const int max_pos = length & ~7; @@ -293,18 +296,18 @@ static void GradientPredictInverse(const uint8_t* const in, _mm_storel_epi64((__m128i*)&row[i], out); } for (; i < length; ++i) { - row[i] = in[i] + GradientPredictorC(row[i - 1], top[i], top[i - 1]); + row[i] = in[i] + GradientPredictor_SSE2(row[i - 1], top[i], top[i - 1]); } } } -static void GradientUnfilter(const uint8_t* prev, const uint8_t* in, - uint8_t* out, int width) { +static void GradientUnfilter_SSE2(const uint8_t* prev, const uint8_t* in, + uint8_t* out, int width) { if (prev == NULL) { - HorizontalUnfilter(NULL, in, out, width); + HorizontalUnfilter_SSE2(NULL, in, out, width); } else { out[0] = in[0] + prev[0]; // predict from above - GradientPredictInverse(in + 1, prev + 1, out + 1, width - 1); + GradientPredictInverse_SSE2(in + 1, prev + 1, out + 1, width - 1); } } @@ -314,13 +317,13 @@ static void GradientUnfilter(const uint8_t* prev, const uint8_t* in, extern void VP8FiltersInitSSE2(void); WEBP_TSAN_IGNORE_FUNCTION void VP8FiltersInitSSE2(void) { - WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter; - WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter; - WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter; + WebPUnfilters[WEBP_FILTER_HORIZONTAL] = HorizontalUnfilter_SSE2; + WebPUnfilters[WEBP_FILTER_VERTICAL] = VerticalUnfilter_SSE2; + WebPUnfilters[WEBP_FILTER_GRADIENT] = GradientUnfilter_SSE2; - WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter; - WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter; - WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter; + WebPFilters[WEBP_FILTER_HORIZONTAL] = HorizontalFilter_SSE2; + WebPFilters[WEBP_FILTER_VERTICAL] = VerticalFilter_SSE2; + WebPFilters[WEBP_FILTER_GRADIENT] = GradientFilter_SSE2; } #else // !WEBP_USE_SSE2 diff --git a/3rdparty/libwebp/dsp/lossless.c b/3rdparty/libwebp/src/dsp/lossless.c similarity index 79% rename from 3rdparty/libwebp/dsp/lossless.c rename to 3rdparty/libwebp/src/dsp/lossless.c index 20d18f6ecd..83f553d9ad 100644 --- a/3rdparty/libwebp/dsp/lossless.c +++ b/3rdparty/libwebp/src/dsp/lossless.c @@ -13,14 +13,15 @@ // Jyrki Alakuijala (jyrki@google.com) // Urvang Joshi (urvang@google.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" +#include #include #include -#include "../dec/vp8li_dec.h" -#include "../utils/endian_inl_utils.h" -#include "./lossless.h" -#include "./lossless_common.h" +#include "src/dec/vp8li_dec.h" +#include "src/utils/endian_inl_utils.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" #define MAX_DIFF_COST (1e30f) @@ -80,8 +81,9 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, return ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; } -// gcc-4.9 on ARM generates incorrect code in Select() when Sub3() is inlined. -#if defined(__arm__) && LOCAL_GCC_VERSION == 0x409 +// gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is +// inlined. +#if defined(__arm__) && LOCAL_GCC_VERSION <= 0x409 # define LOCAL_INLINE __attribute__ ((noinline)) #else # define LOCAL_INLINE WEBP_INLINE @@ -107,69 +109,69 @@ static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { //------------------------------------------------------------------------------ // Predictors -static uint32_t Predictor0(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor0_C(uint32_t left, const uint32_t* const top) { (void)top; (void)left; return ARGB_BLACK; } -static uint32_t Predictor1(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor1_C(uint32_t left, const uint32_t* const top) { (void)top; return left; } -static uint32_t Predictor2(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor2_C(uint32_t left, const uint32_t* const top) { (void)left; return top[0]; } -static uint32_t Predictor3(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor3_C(uint32_t left, const uint32_t* const top) { (void)left; return top[1]; } -static uint32_t Predictor4(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor4_C(uint32_t left, const uint32_t* const top) { (void)left; return top[-1]; } -static uint32_t Predictor5(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor5_C(uint32_t left, const uint32_t* const top) { const uint32_t pred = Average3(left, top[0], top[1]); return pred; } -static uint32_t Predictor6(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor6_C(uint32_t left, const uint32_t* const top) { const uint32_t pred = Average2(left, top[-1]); return pred; } -static uint32_t Predictor7(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor7_C(uint32_t left, const uint32_t* const top) { const uint32_t pred = Average2(left, top[0]); return pred; } -static uint32_t Predictor8(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor8_C(uint32_t left, const uint32_t* const top) { const uint32_t pred = Average2(top[-1], top[0]); (void)left; return pred; } -static uint32_t Predictor9(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor9_C(uint32_t left, const uint32_t* const top) { const uint32_t pred = Average2(top[0], top[1]); (void)left; return pred; } -static uint32_t Predictor10(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor10_C(uint32_t left, const uint32_t* const top) { const uint32_t pred = Average4(left, top[-1], top[0], top[1]); return pred; } -static uint32_t Predictor11(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor11_C(uint32_t left, const uint32_t* const top) { const uint32_t pred = Select(top[0], left, top[-1]); return pred; } -static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor12_C(uint32_t left, const uint32_t* const top) { const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); return pred; } -static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor13_C(uint32_t left, const uint32_t* const top) { const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); return pred; } -GENERATE_PREDICTOR_ADD(Predictor0, PredictorAdd0) -static void PredictorAdd1(const uint32_t* in, const uint32_t* upper, - int num_pixels, uint32_t* out) { +GENERATE_PREDICTOR_ADD(Predictor0_C, PredictorAdd0_C) +static void PredictorAdd1_C(const uint32_t* in, const uint32_t* upper, + int num_pixels, uint32_t* out) { int i; uint32_t left = out[-1]; for (i = 0; i < num_pixels; ++i) { @@ -177,29 +179,29 @@ static void PredictorAdd1(const uint32_t* in, const uint32_t* upper, } (void)upper; } -GENERATE_PREDICTOR_ADD(Predictor2, PredictorAdd2) -GENERATE_PREDICTOR_ADD(Predictor3, PredictorAdd3) -GENERATE_PREDICTOR_ADD(Predictor4, PredictorAdd4) -GENERATE_PREDICTOR_ADD(Predictor5, PredictorAdd5) -GENERATE_PREDICTOR_ADD(Predictor6, PredictorAdd6) -GENERATE_PREDICTOR_ADD(Predictor7, PredictorAdd7) -GENERATE_PREDICTOR_ADD(Predictor8, PredictorAdd8) -GENERATE_PREDICTOR_ADD(Predictor9, PredictorAdd9) -GENERATE_PREDICTOR_ADD(Predictor10, PredictorAdd10) -GENERATE_PREDICTOR_ADD(Predictor11, PredictorAdd11) -GENERATE_PREDICTOR_ADD(Predictor12, PredictorAdd12) -GENERATE_PREDICTOR_ADD(Predictor13, PredictorAdd13) +GENERATE_PREDICTOR_ADD(Predictor2_C, PredictorAdd2_C) +GENERATE_PREDICTOR_ADD(Predictor3_C, PredictorAdd3_C) +GENERATE_PREDICTOR_ADD(Predictor4_C, PredictorAdd4_C) +GENERATE_PREDICTOR_ADD(Predictor5_C, PredictorAdd5_C) +GENERATE_PREDICTOR_ADD(Predictor6_C, PredictorAdd6_C) +GENERATE_PREDICTOR_ADD(Predictor7_C, PredictorAdd7_C) +GENERATE_PREDICTOR_ADD(Predictor8_C, PredictorAdd8_C) +GENERATE_PREDICTOR_ADD(Predictor9_C, PredictorAdd9_C) +GENERATE_PREDICTOR_ADD(Predictor10_C, PredictorAdd10_C) +GENERATE_PREDICTOR_ADD(Predictor11_C, PredictorAdd11_C) +GENERATE_PREDICTOR_ADD(Predictor12_C, PredictorAdd12_C) +GENERATE_PREDICTOR_ADD(Predictor13_C, PredictorAdd13_C) //------------------------------------------------------------------------------ // Inverse prediction. -static void PredictorInverseTransform(const VP8LTransform* const transform, - int y_start, int y_end, - const uint32_t* in, uint32_t* out) { +static void PredictorInverseTransform_C(const VP8LTransform* const transform, + int y_start, int y_end, + const uint32_t* in, uint32_t* out) { const int width = transform->xsize_; if (y_start == 0) { // First Row follows the L (mode=1) mode. - PredictorAdd0(in, NULL, 1, out); - PredictorAdd1(in + 1, NULL, width - 1, out + 1); + PredictorAdd0_C(in, NULL, 1, out); + PredictorAdd1_C(in + 1, NULL, width - 1, out + 1); in += width; out += width; ++y_start; @@ -217,7 +219,7 @@ static void PredictorInverseTransform(const VP8LTransform* const transform, const uint32_t* pred_mode_src = pred_mode_base; int x = 1; // First pixel follows the T (mode=2) mode. - PredictorAdd2(in, out - width, 1, out); + PredictorAdd2_C(in, out - width, 1, out); // .. the rest: while (x < width) { const VP8LPredictorAddSubFunc pred_func = @@ -272,8 +274,8 @@ void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, const uint32_t argb = src[i]; const uint32_t green = argb >> 8; const uint32_t red = argb >> 16; - int new_red = red; - int new_blue = argb; + int new_red = red & 0xff; + int new_blue = argb & 0xff; new_red += ColorTransformDelta(m->green_to_red_, green); new_red &= 0xff; new_blue += ColorTransformDelta(m->green_to_blue_, green); @@ -284,9 +286,9 @@ void VP8LTransformColorInverse_C(const VP8LMultipliers* const m, } // Color space inverse transform. -static void ColorSpaceInverseTransform(const VP8LTransform* const transform, - int y_start, int y_end, - const uint32_t* src, uint32_t* dst) { +static void ColorSpaceInverseTransform_C(const VP8LTransform* const transform, + int y_start, int y_end, + const uint32_t* src, uint32_t* dst) { const int width = transform->xsize_; const int tile_width = 1 << transform->bits_; const int mask = tile_width - 1; @@ -362,10 +364,10 @@ STATIC_DECL void FUNC_NAME(const VP8LTransform* const transform, \ } \ } -COLOR_INDEX_INVERSE(ColorIndexInverseTransform, MapARGB, static, uint32_t, 32b, - VP8GetARGBIndex, VP8GetARGBValue) -COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, MapAlpha, , uint8_t, - 8b, VP8GetAlphaIndex, VP8GetAlphaValue) +COLOR_INDEX_INVERSE(ColorIndexInverseTransform_C, MapARGB_C, static, + uint32_t, 32b, VP8GetARGBIndex, VP8GetARGBValue) +COLOR_INDEX_INVERSE(VP8LColorIndexInverseTransformAlpha, MapAlpha_C, , + uint8_t, 8b, VP8GetAlphaIndex, VP8GetAlphaValue) #undef COLOR_INDEX_INVERSE @@ -380,7 +382,7 @@ void VP8LInverseTransform(const VP8LTransform* const transform, VP8LAddGreenToBlueAndRed(in, (row_end - row_start) * width, out); break; case PREDICTOR_TRANSFORM: - PredictorInverseTransform(transform, row_start, row_end, in, out); + PredictorInverseTransform_C(transform, row_start, row_end, in, out); if (row_end != transform->ysize_) { // The last predicted row in this iteration will be the top-pred row // for the first row in next iteration. @@ -389,7 +391,7 @@ void VP8LInverseTransform(const VP8LTransform* const transform, } break; case CROSS_COLOR_TRANSFORM: - ColorSpaceInverseTransform(transform, row_start, row_end, in, out); + ColorSpaceInverseTransform_C(transform, row_start, row_end, in, out); break; case COLOR_INDEXING_TRANSFORM: if (in == out && transform->bits_ > 0) { @@ -403,9 +405,9 @@ void VP8LInverseTransform(const VP8LTransform* const transform, VP8LSubSampleSize(transform->xsize_, transform->bits_); uint32_t* const src = out + out_stride - in_stride; memmove(src, out, in_stride * sizeof(*src)); - ColorIndexInverseTransform(transform, row_start, row_end, src, out); + ColorIndexInverseTransform_C(transform, row_start, row_end, src, out); } else { - ColorIndexInverseTransform(transform, row_start, row_end, in, out); + ColorIndexInverseTransform_C(transform, row_start, row_end, in, out); } break; } @@ -452,7 +454,7 @@ void VP8LConvertBGRAToRGBA4444_C(const uint32_t* src, const uint32_t argb = *src++; const uint8_t rg = ((argb >> 16) & 0xf0) | ((argb >> 12) & 0xf); const uint8_t ba = ((argb >> 0) & 0xf0) | ((argb >> 28) & 0xf); -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) *dst++ = ba; *dst++ = rg; #else @@ -469,7 +471,7 @@ void VP8LConvertBGRAToRGB565_C(const uint32_t* src, const uint32_t argb = *src++; const uint8_t rg = ((argb >> 16) & 0xf8) | ((argb >> 13) & 0x7); const uint8_t gb = ((argb >> 5) & 0xe0) | ((argb >> 3) & 0x1f); -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) *dst++ = gb; *dst++ = rg; #else @@ -496,22 +498,7 @@ static void CopyOrSwap(const uint32_t* src, int num_pixels, uint8_t* dst, const uint32_t* const src_end = src + num_pixels; while (src < src_end) { const uint32_t argb = *src++; - -#if !defined(WORDS_BIGENDIAN) -#if !defined(WEBP_REFERENCE_IMPLEMENTATION) WebPUint32ToMem(dst, BSwap32(argb)); -#else // WEBP_REFERENCE_IMPLEMENTATION - dst[0] = (argb >> 24) & 0xff; - dst[1] = (argb >> 16) & 0xff; - dst[2] = (argb >> 8) & 0xff; - dst[3] = (argb >> 0) & 0xff; -#endif -#else // WORDS_BIGENDIAN - dst[0] = (argb >> 0) & 0xff; - dst[1] = (argb >> 8) & 0xff; - dst[2] = (argb >> 16) & 0xff; - dst[3] = (argb >> 24) & 0xff; -#endif dst += sizeof(argb); } } else { @@ -593,23 +580,23 @@ extern void VP8LDspInitMSA(void); static volatile VP8CPUInfo lossless_last_cpuinfo_used = (VP8CPUInfo)&lossless_last_cpuinfo_used; -#define COPY_PREDICTOR_ARRAY(IN, OUT) do { \ - (OUT)[0] = IN##0; \ - (OUT)[1] = IN##1; \ - (OUT)[2] = IN##2; \ - (OUT)[3] = IN##3; \ - (OUT)[4] = IN##4; \ - (OUT)[5] = IN##5; \ - (OUT)[6] = IN##6; \ - (OUT)[7] = IN##7; \ - (OUT)[8] = IN##8; \ - (OUT)[9] = IN##9; \ - (OUT)[10] = IN##10; \ - (OUT)[11] = IN##11; \ - (OUT)[12] = IN##12; \ - (OUT)[13] = IN##13; \ - (OUT)[14] = IN##0; /* <- padding security sentinels*/ \ - (OUT)[15] = IN##0; \ +#define COPY_PREDICTOR_ARRAY(IN, OUT) do { \ + (OUT)[0] = IN##0_C; \ + (OUT)[1] = IN##1_C; \ + (OUT)[2] = IN##2_C; \ + (OUT)[3] = IN##3_C; \ + (OUT)[4] = IN##4_C; \ + (OUT)[5] = IN##5_C; \ + (OUT)[6] = IN##6_C; \ + (OUT)[7] = IN##7_C; \ + (OUT)[8] = IN##8_C; \ + (OUT)[9] = IN##9_C; \ + (OUT)[10] = IN##10_C; \ + (OUT)[11] = IN##11_C; \ + (OUT)[12] = IN##12_C; \ + (OUT)[13] = IN##13_C; \ + (OUT)[14] = IN##0_C; /* <- padding security sentinels*/ \ + (OUT)[15] = IN##0_C; \ } while (0); WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) { @@ -620,18 +607,21 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) { COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd) COPY_PREDICTOR_ARRAY(PredictorAdd, VP8LPredictorsAdd_C) +#if !WEBP_NEON_OMIT_C_CODE VP8LAddGreenToBlueAndRed = VP8LAddGreenToBlueAndRed_C; VP8LTransformColorInverse = VP8LTransformColorInverse_C; - VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C; VP8LConvertBGRAToRGBA = VP8LConvertBGRAToRGBA_C; + VP8LConvertBGRAToRGB = VP8LConvertBGRAToRGB_C; + VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C; +#endif + VP8LConvertBGRAToRGBA4444 = VP8LConvertBGRAToRGBA4444_C; VP8LConvertBGRAToRGB565 = VP8LConvertBGRAToRGB565_C; - VP8LConvertBGRAToBGR = VP8LConvertBGRAToBGR_C; - VP8LMapColor32b = MapARGB; - VP8LMapColor8b = MapAlpha; + VP8LMapColor32b = MapARGB_C; + VP8LMapColor8b = MapAlpha_C; // If defined, use CPUInfo() to overwrite some pointers with faster versions. if (VP8GetCPUInfo != NULL) { @@ -640,11 +630,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) { VP8LDspInitSSE2(); } #endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8LDspInitNEON(); - } -#endif #if defined(WEBP_USE_MIPS_DSP_R2) if (VP8GetCPUInfo(kMIPSdspR2)) { VP8LDspInitMIPSdspR2(); @@ -656,6 +641,24 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInit(void) { } #endif } + +#if defined(WEBP_USE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8LDspInitNEON(); + } +#endif + + assert(VP8LAddGreenToBlueAndRed != NULL); + assert(VP8LTransformColorInverse != NULL); + assert(VP8LConvertBGRAToRGBA != NULL); + assert(VP8LConvertBGRAToRGB != NULL); + assert(VP8LConvertBGRAToBGR != NULL); + assert(VP8LConvertBGRAToRGBA4444 != NULL); + assert(VP8LConvertBGRAToRGB565 != NULL); + assert(VP8LMapColor32b != NULL); + assert(VP8LMapColor8b != NULL); + lossless_last_cpuinfo_used = VP8GetCPUInfo; } #undef COPY_PREDICTOR_ARRAY diff --git a/3rdparty/libwebp/dsp/lossless.h b/3rdparty/libwebp/src/dsp/lossless.h similarity index 97% rename from 3rdparty/libwebp/dsp/lossless.h rename to 3rdparty/libwebp/src/dsp/lossless.h index 352a54e509..a99dbda686 100644 --- a/3rdparty/libwebp/dsp/lossless.h +++ b/3rdparty/libwebp/src/dsp/lossless.h @@ -15,18 +15,18 @@ #ifndef WEBP_DSP_LOSSLESS_H_ #define WEBP_DSP_LOSSLESS_H_ -#include "../webp/types.h" -#include "../webp/decode.h" +#include "src/webp/types.h" +#include "src/webp/decode.h" -#include "../enc/histogram_enc.h" -#include "../utils/utils.h" +#include "src/enc/histogram_enc.h" +#include "src/utils/utils.h" #ifdef __cplusplus extern "C" { #endif #ifdef WEBP_EXPERIMENTAL_FEATURES -#include "../enc/delta_palettization_enc.h" +#include "src/enc/delta_palettization_enc.h" #endif // WEBP_EXPERIMENTAL_FEATURES //------------------------------------------------------------------------------ @@ -124,7 +124,7 @@ void VP8LDspInit(void); typedef void (*VP8LProcessEncBlueAndRedFunc)(uint32_t* dst, int num_pixels); extern VP8LProcessEncBlueAndRedFunc VP8LSubtractGreenFromBlueAndRed; typedef void (*VP8LTransformColorFunc)(const VP8LMultipliers* const m, - uint32_t* const dst, int num_pixels); + uint32_t* dst, int num_pixels); extern VP8LTransformColorFunc VP8LTransformColor; typedef void (*VP8LCollectColorBlueTransformsFunc)( const uint32_t* argb, int stride, diff --git a/3rdparty/libwebp/dsp/lossless_common.h b/3rdparty/libwebp/src/dsp/lossless_common.h similarity index 96% rename from 3rdparty/libwebp/dsp/lossless_common.h rename to 3rdparty/libwebp/src/dsp/lossless_common.h index c40f711208..a2648d1737 100644 --- a/3rdparty/libwebp/dsp/lossless_common.h +++ b/3rdparty/libwebp/src/dsp/lossless_common.h @@ -16,9 +16,9 @@ #ifndef WEBP_DSP_LOSSLESS_COMMON_H_ #define WEBP_DSP_LOSSLESS_COMMON_H_ -#include "../webp/types.h" +#include "src/webp/types.h" -#include "../utils/utils.h" +#include "src/utils/utils.h" #ifdef __cplusplus extern "C" { @@ -93,14 +93,6 @@ static WEBP_INLINE float VP8LFastSLog2(uint32_t v) { // ----------------------------------------------------------------------------- // PrefixEncode() -static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) { - const int log_floor = BitsLog2Floor(n); - if (n == (n & ~(n - 1))) { // zero or a power of two. - return log_floor; - } - return log_floor + 1; -} - // Splitting of distance and length codes into prefixes and // extra bits. The prefixes are encoded with an entropy code // while the extra bits are stored just as normal bits. diff --git a/3rdparty/libwebp/dsp/lossless_enc.c b/3rdparty/libwebp/src/dsp/lossless_enc.c similarity index 90% rename from 3rdparty/libwebp/dsp/lossless_enc.c rename to 3rdparty/libwebp/src/dsp/lossless_enc.c index 4e46fbab8b..92ca3c0542 100644 --- a/3rdparty/libwebp/dsp/lossless_enc.c +++ b/3rdparty/libwebp/src/dsp/lossless_enc.c @@ -13,15 +13,16 @@ // Jyrki Alakuijala (jyrki@google.com) // Urvang Joshi (urvang@google.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" +#include #include #include -#include "../dec/vp8li_dec.h" -#include "../utils/endian_inl_utils.h" -#include "./lossless.h" -#include "./lossless_common.h" -#include "./yuv.h" +#include "src/dec/vp8li_dec.h" +#include "src/utils/endian_inl_utils.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/dsp/yuv.h" // lookup table for small values of log2(int) const float kLog2Table[LOG_LOOKUP_IDX_MAX] = { @@ -325,7 +326,7 @@ const uint8_t kPrefixEncodeExtraBitsValue[PREFIX_LOOKUP_IDX_MAX] = { 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126 }; -static float FastSLog2Slow(uint32_t v) { +static float FastSLog2Slow_C(uint32_t v) { assert(v >= LOG_LOOKUP_IDX_MAX); if (v < APPROX_LOG_WITH_CORRECTION_MAX) { int log_cnt = 0; @@ -351,7 +352,7 @@ static float FastSLog2Slow(uint32_t v) { } } -static float FastLog2Slow(uint32_t v) { +static float FastLog2Slow_C(uint32_t v) { assert(v >= LOG_LOOKUP_IDX_MAX); if (v < APPROX_LOG_WITH_CORRECTION_MAX) { int log_cnt = 0; @@ -380,7 +381,7 @@ static float FastLog2Slow(uint32_t v) { // Methods to calculate Entropy (Shannon). // Compute the combined Shanon's entropy for distribution {X} and {X+Y} -static float CombinedShannonEntropy(const int X[256], const int Y[256]) { +static float CombinedShannonEntropy_C(const int X[256], const int Y[256]) { int i; double retval = 0.; int sumX = 0, sumXY = 0; @@ -453,9 +454,9 @@ static WEBP_INLINE void GetEntropyUnrefinedHelper( *i_prev = i; } -static void GetEntropyUnrefined(const uint32_t X[], int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats) { +static void GetEntropyUnrefined_C(const uint32_t X[], int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats) { int i; int i_prev = 0; uint32_t x_prev = X[0]; @@ -474,10 +475,11 @@ static void GetEntropyUnrefined(const uint32_t X[], int length, bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); } -static void GetCombinedEntropyUnrefined(const uint32_t X[], const uint32_t Y[], - int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats) { +static void GetCombinedEntropyUnrefined_C(const uint32_t X[], + const uint32_t Y[], + int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats) { int i = 1; int i_prev = 0; uint32_t xy_prev = X[0] + Y[0]; @@ -520,8 +522,8 @@ void VP8LTransformColor_C(const VP8LMultipliers* const m, uint32_t* data, const uint32_t argb = data[i]; const uint32_t green = argb >> 8; const uint32_t red = argb >> 16; - int new_red = red; - int new_blue = argb; + int new_red = red & 0xff; + int new_blue = argb & 0xff; new_red -= ColorTransformDelta(m->green_to_red_, green); new_red &= 0xff; new_blue -= ColorTransformDelta(m->green_to_blue_, green); @@ -577,8 +579,8 @@ void VP8LCollectColorBlueTransforms_C(const uint32_t* argb, int stride, //------------------------------------------------------------------------------ -static int VectorMismatch(const uint32_t* const array1, - const uint32_t* const array2, int length) { +static int VectorMismatch_C(const uint32_t* const array1, + const uint32_t* const array2, int length) { int match_len = 0; while (match_len < length && array1[match_len] == array2[match_len]) { @@ -610,15 +612,15 @@ void VP8LBundleColorMap_C(const uint8_t* const row, int width, int xbits, //------------------------------------------------------------------------------ -static double ExtraCost(const uint32_t* population, int length) { +static double ExtraCost_C(const uint32_t* population, int length) { int i; double cost = 0.; for (i = 2; i < length - 2; ++i) cost += (i >> 1) * population[i + 2]; return cost; } -static double ExtraCostCombined(const uint32_t* X, const uint32_t* Y, - int length) { +static double ExtraCostCombined_C(const uint32_t* X, const uint32_t* Y, + int length) { int i; double cost = 0.; for (i = 2; i < length - 2; ++i) { @@ -630,9 +632,9 @@ static double ExtraCostCombined(const uint32_t* X, const uint32_t* Y, //------------------------------------------------------------------------------ -static void HistogramAdd(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out) { +static void HistogramAdd_C(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out) { int i; const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_); assert(a->palette_code_bits_ == b->palette_code_bits_); @@ -869,26 +871,28 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) { VP8LDspInit(); +#if !WEBP_NEON_OMIT_C_CODE VP8LSubtractGreenFromBlueAndRed = VP8LSubtractGreenFromBlueAndRed_C; VP8LTransformColor = VP8LTransformColor_C; +#endif VP8LCollectColorBlueTransforms = VP8LCollectColorBlueTransforms_C; VP8LCollectColorRedTransforms = VP8LCollectColorRedTransforms_C; - VP8LFastLog2Slow = FastLog2Slow; - VP8LFastSLog2Slow = FastSLog2Slow; + VP8LFastLog2Slow = FastLog2Slow_C; + VP8LFastSLog2Slow = FastSLog2Slow_C; - VP8LExtraCost = ExtraCost; - VP8LExtraCostCombined = ExtraCostCombined; - VP8LCombinedShannonEntropy = CombinedShannonEntropy; + VP8LExtraCost = ExtraCost_C; + VP8LExtraCostCombined = ExtraCostCombined_C; + VP8LCombinedShannonEntropy = CombinedShannonEntropy_C; - VP8LGetEntropyUnrefined = GetEntropyUnrefined; - VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined; + VP8LGetEntropyUnrefined = GetEntropyUnrefined_C; + VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_C; - VP8LHistogramAdd = HistogramAdd; + VP8LHistogramAdd = HistogramAdd_C; - VP8LVectorMismatch = VectorMismatch; + VP8LVectorMismatch = VectorMismatch_C; VP8LBundleColorMap = VP8LBundleColorMap_C; VP8LPredictorsSub[0] = PredictorSub0_C; @@ -937,11 +941,6 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) { #endif } #endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - VP8LEncDspInitNEON(); - } -#endif #if defined(WEBP_USE_MIPS32) if (VP8GetCPUInfo(kMIPS32)) { VP8LEncDspInitMIPS32(); @@ -958,6 +957,61 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInit(void) { } #endif } + +#if defined(WEBP_USE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + VP8LEncDspInitNEON(); + } +#endif + + assert(VP8LSubtractGreenFromBlueAndRed != NULL); + assert(VP8LTransformColor != NULL); + assert(VP8LCollectColorBlueTransforms != NULL); + assert(VP8LCollectColorRedTransforms != NULL); + assert(VP8LFastLog2Slow != NULL); + assert(VP8LFastSLog2Slow != NULL); + assert(VP8LExtraCost != NULL); + assert(VP8LExtraCostCombined != NULL); + assert(VP8LCombinedShannonEntropy != NULL); + assert(VP8LGetEntropyUnrefined != NULL); + assert(VP8LGetCombinedEntropyUnrefined != NULL); + assert(VP8LHistogramAdd != NULL); + assert(VP8LVectorMismatch != NULL); + assert(VP8LBundleColorMap != NULL); + assert(VP8LPredictorsSub[0] != NULL); + assert(VP8LPredictorsSub[1] != NULL); + assert(VP8LPredictorsSub[2] != NULL); + assert(VP8LPredictorsSub[3] != NULL); + assert(VP8LPredictorsSub[4] != NULL); + assert(VP8LPredictorsSub[5] != NULL); + assert(VP8LPredictorsSub[6] != NULL); + assert(VP8LPredictorsSub[7] != NULL); + assert(VP8LPredictorsSub[8] != NULL); + assert(VP8LPredictorsSub[9] != NULL); + assert(VP8LPredictorsSub[10] != NULL); + assert(VP8LPredictorsSub[11] != NULL); + assert(VP8LPredictorsSub[12] != NULL); + assert(VP8LPredictorsSub[13] != NULL); + assert(VP8LPredictorsSub[14] != NULL); + assert(VP8LPredictorsSub[15] != NULL); + assert(VP8LPredictorsSub_C[0] != NULL); + assert(VP8LPredictorsSub_C[1] != NULL); + assert(VP8LPredictorsSub_C[2] != NULL); + assert(VP8LPredictorsSub_C[3] != NULL); + assert(VP8LPredictorsSub_C[4] != NULL); + assert(VP8LPredictorsSub_C[5] != NULL); + assert(VP8LPredictorsSub_C[6] != NULL); + assert(VP8LPredictorsSub_C[7] != NULL); + assert(VP8LPredictorsSub_C[8] != NULL); + assert(VP8LPredictorsSub_C[9] != NULL); + assert(VP8LPredictorsSub_C[10] != NULL); + assert(VP8LPredictorsSub_C[11] != NULL); + assert(VP8LPredictorsSub_C[12] != NULL); + assert(VP8LPredictorsSub_C[13] != NULL); + assert(VP8LPredictorsSub_C[14] != NULL); + assert(VP8LPredictorsSub_C[15] != NULL); + lossless_enc_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/3rdparty/libwebp/dsp/lossless_enc_mips32.c b/3rdparty/libwebp/src/dsp/lossless_enc_mips32.c similarity index 89% rename from 3rdparty/libwebp/dsp/lossless_enc_mips32.c rename to 3rdparty/libwebp/src/dsp/lossless_enc_mips32.c index 4186b9f50d..e7b58f4e8c 100644 --- a/3rdparty/libwebp/dsp/lossless_enc_mips32.c +++ b/3rdparty/libwebp/src/dsp/lossless_enc_mips32.c @@ -12,9 +12,9 @@ // Author(s): Djordje Pesut (djordje.pesut@imgtec.com) // Jovan Zelincevic (jovan.zelincevic@imgtec.com) -#include "./dsp.h" -#include "./lossless.h" -#include "./lossless_common.h" +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" #if defined(WEBP_USE_MIPS32) @@ -23,7 +23,7 @@ #include #include -static float FastSLog2Slow(uint32_t v) { +static float FastSLog2Slow_MIPS32(uint32_t v) { assert(v >= LOG_LOOKUP_IDX_MAX); if (v < APPROX_LOG_WITH_CORRECTION_MAX) { uint32_t log_cnt, y, correction; @@ -59,7 +59,7 @@ static float FastSLog2Slow(uint32_t v) { } } -static float FastLog2Slow(uint32_t v) { +static float FastLog2Slow_MIPS32(uint32_t v) { assert(v >= LOG_LOOKUP_IDX_MAX); if (v < APPROX_LOG_WITH_CORRECTION_MAX) { uint32_t log_cnt, y; @@ -104,7 +104,7 @@ static float FastLog2Slow(uint32_t v) { // pop += 2; // } // return (double)cost; -static double ExtraCost(const uint32_t* const population, int length) { +static double ExtraCost_MIPS32(const uint32_t* const population, int length) { int i, temp0, temp1; const uint32_t* pop = &population[4]; const uint32_t* const LoopEnd = &population[length]; @@ -149,8 +149,8 @@ static double ExtraCost(const uint32_t* const population, int length) { // pY += 2; // } // return (double)cost; -static double ExtraCostCombined(const uint32_t* const X, - const uint32_t* const Y, int length) { +static double ExtraCostCombined_MIPS32(const uint32_t* const X, + const uint32_t* const Y, int length) { int i, temp0, temp1, temp2, temp3; const uint32_t* pX = &X[4]; const uint32_t* pY = &Y[4]; @@ -241,9 +241,9 @@ static WEBP_INLINE void GetEntropyUnrefinedHelper( *i_prev = i; } -static void GetEntropyUnrefined(const uint32_t X[], int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats) { +static void GetEntropyUnrefined_MIPS32(const uint32_t X[], int length, + VP8LBitEntropy* const bit_entropy, + VP8LStreaks* const stats) { int i; int i_prev = 0; uint32_t x_prev = X[0]; @@ -262,26 +262,27 @@ static void GetEntropyUnrefined(const uint32_t X[], int length, bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); } -static void GetCombinedEntropyUnrefined(const uint32_t X[], const uint32_t Y[], - int length, - VP8LBitEntropy* const bit_entropy, - VP8LStreaks* const stats) { +static void GetCombinedEntropyUnrefined_MIPS32(const uint32_t X[], + const uint32_t Y[], + int length, + VP8LBitEntropy* const entropy, + VP8LStreaks* const stats) { int i = 1; int i_prev = 0; uint32_t xy_prev = X[0] + Y[0]; memset(stats, 0, sizeof(*stats)); - VP8LBitEntropyInit(bit_entropy); + VP8LBitEntropyInit(entropy); for (i = 1; i < length; ++i) { const uint32_t xy = X[i] + Y[i]; if (xy != xy_prev) { - GetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, bit_entropy, stats); + GetEntropyUnrefinedHelper(xy, i, &xy_prev, &i_prev, entropy, stats); } } - GetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, bit_entropy, stats); + GetEntropyUnrefinedHelper(0, i, &xy_prev, &i_prev, entropy, stats); - bit_entropy->entropy += VP8LFastSLog2(bit_entropy->sum); + entropy->entropy += VP8LFastSLog2(entropy->sum); } #define ASM_START \ @@ -374,9 +375,9 @@ static void GetCombinedEntropyUnrefined(const uint32_t X[], const uint32_t Y[], } \ } while (0) -static void HistogramAdd(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out) { +static void HistogramAdd_MIPS32(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out) { uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; const int extra_cache_size = VP8LHistogramNumCodes(a->palette_code_bits_) - (NUM_LITERAL_CODES + NUM_LENGTH_CODES); @@ -415,13 +416,13 @@ static void HistogramAdd(const VP8LHistogram* const a, extern void VP8LEncDspInitMIPS32(void); WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) { - VP8LFastSLog2Slow = FastSLog2Slow; - VP8LFastLog2Slow = FastLog2Slow; - VP8LExtraCost = ExtraCost; - VP8LExtraCostCombined = ExtraCostCombined; - VP8LGetEntropyUnrefined = GetEntropyUnrefined; - VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined; - VP8LHistogramAdd = HistogramAdd; + VP8LFastSLog2Slow = FastSLog2Slow_MIPS32; + VP8LFastLog2Slow = FastLog2Slow_MIPS32; + VP8LExtraCost = ExtraCost_MIPS32; + VP8LExtraCostCombined = ExtraCostCombined_MIPS32; + VP8LGetEntropyUnrefined = GetEntropyUnrefined_MIPS32; + VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_MIPS32; + VP8LHistogramAdd = HistogramAdd_MIPS32; } #else // !WEBP_USE_MIPS32 diff --git a/3rdparty/libwebp/dsp/lossless_enc_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c similarity index 89% rename from 3rdparty/libwebp/dsp/lossless_enc_mips_dsp_r2.c rename to 3rdparty/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c index 0abf3c4f36..5855e6ae15 100644 --- a/3rdparty/libwebp/dsp/lossless_enc_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/lossless_enc_mips_dsp_r2.c @@ -12,14 +12,14 @@ // Author(s): Djordje Pesut (djordje.pesut@imgtec.com) // Jovan Zelincevic (jovan.zelincevic@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS_DSP_R2) -#include "./lossless.h" +#include "src/dsp/lossless.h" -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, - int num_pixels) { +static void SubtractGreenFromBlueAndRed_MIPSdspR2(uint32_t* argb_data, + int num_pixels) { uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; uint32_t* const p_loop1_end = argb_data + (num_pixels & ~3); uint32_t* const p_loop2_end = p_loop1_end + (num_pixels & 3); @@ -78,8 +78,8 @@ static WEBP_INLINE uint32_t ColorTransformDelta(int8_t color_pred, return (uint32_t)((int)(color_pred) * color) >> 5; } -static void TransformColor(const VP8LMultipliers* const m, uint32_t* data, - int num_pixels) { +static void TransformColor_MIPSdspR2(const VP8LMultipliers* const m, + uint32_t* data, int num_pixels) { int temp0, temp1, temp2, temp3, temp4, temp5; uint32_t argb, argb1, new_red, new_red1; const uint32_t G_to_R = m->green_to_red_; @@ -171,10 +171,13 @@ static WEBP_INLINE uint8_t TransformColorBlue(uint8_t green_to_blue, return (new_blue & 0xff); } -static void CollectColorBlueTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, - int histo[]) { +static void CollectColorBlueTransforms_MIPSdspR2(const uint32_t* argb, + int stride, + int tile_width, + int tile_height, + int green_to_blue, + int red_to_blue, + int histo[]) { const int rtb = (red_to_blue << 16) | (red_to_blue & 0xffff); const int gtb = (green_to_blue << 16) | (green_to_blue & 0xffff); const uint32_t mask = 0xff00ffu; @@ -222,9 +225,12 @@ static WEBP_INLINE uint8_t TransformColorRed(uint8_t green_to_red, return (new_red & 0xff); } -static void CollectColorRedTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]) { +static void CollectColorRedTransforms_MIPSdspR2(const uint32_t* argb, + int stride, + int tile_width, + int tile_height, + int green_to_red, + int histo[]) { const int gtr = (green_to_red << 16) | (green_to_red & 0xffff); while (tile_height-- > 0) { int x; @@ -262,10 +268,10 @@ static void CollectColorRedTransforms(const uint32_t* argb, int stride, extern void VP8LEncDspInitMIPSdspR2(void); WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPSdspR2(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; - VP8LTransformColor = TransformColor; - VP8LCollectColorBlueTransforms = CollectColorBlueTransforms; - VP8LCollectColorRedTransforms = CollectColorRedTransforms; + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_MIPSdspR2; + VP8LTransformColor = TransformColor_MIPSdspR2; + VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_MIPSdspR2; + VP8LCollectColorRedTransforms = CollectColorRedTransforms_MIPSdspR2; } #else // !WEBP_USE_MIPS_DSP_R2 diff --git a/3rdparty/libwebp/dsp/lossless_enc_msa.c b/3rdparty/libwebp/src/dsp/lossless_enc_msa.c similarity index 92% rename from 3rdparty/libwebp/dsp/lossless_enc_msa.c rename to 3rdparty/libwebp/src/dsp/lossless_enc_msa.c index 2f69ba3bca..600dddfb59 100644 --- a/3rdparty/libwebp/dsp/lossless_enc_msa.c +++ b/3rdparty/libwebp/src/dsp/lossless_enc_msa.c @@ -11,12 +11,12 @@ // // Authors: Prashant Patil (Prashant.Patil@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MSA) -#include "./lossless.h" -#include "./msa_macro.h" +#include "src/dsp/lossless.h" +#include "src/dsp/msa_macro.h" #define TRANSFORM_COLOR_8(src0, src1, dst0, dst1, c0, c1, mask0, mask1) do { \ v8i16 g0, g1, t0, t1, t2, t3; \ @@ -48,8 +48,8 @@ dst = VSHF_UB(src, t0, mask1); \ } while (0) -static void TransformColor(const VP8LMultipliers* const m, uint32_t* data, - int num_pixels) { +static void TransformColor_MSA(const VP8LMultipliers* const m, uint32_t* data, + int num_pixels) { v16u8 src0, dst0; const v16i8 g2br = (v16i8)__msa_fill_w(m->green_to_blue_ | (m->green_to_red_ << 16)); @@ -94,7 +94,8 @@ static void TransformColor(const VP8LMultipliers* const m, uint32_t* data, } } -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { +static void SubtractGreenFromBlueAndRed_MSA(uint32_t* argb_data, + int num_pixels) { int i; uint8_t* ptemp_data = (uint8_t*)argb_data; v16u8 src0, dst0, tmp0; @@ -136,8 +137,8 @@ static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { extern void VP8LEncDspInitMSA(void); WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMSA(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; - VP8LTransformColor = TransformColor; + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_MSA; + VP8LTransformColor = TransformColor_MSA; } #else // !WEBP_USE_MSA diff --git a/3rdparty/libwebp/dsp/lossless_enc_neon.c b/3rdparty/libwebp/src/dsp/lossless_enc_neon.c similarity index 82% rename from 3rdparty/libwebp/dsp/lossless_enc_neon.c rename to 3rdparty/libwebp/src/dsp/lossless_enc_neon.c index 4c56f2594b..7c7b73f8b6 100644 --- a/3rdparty/libwebp/dsp/lossless_enc_neon.c +++ b/3rdparty/libwebp/src/dsp/lossless_enc_neon.c @@ -11,14 +11,14 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_NEON) #include -#include "./lossless.h" -#include "./neon.h" +#include "src/dsp/lossless.h" +#include "src/dsp/neon.h" //------------------------------------------------------------------------------ // Subtract-Green Transform @@ -36,8 +36,8 @@ static const uint8_t kGreenShuffle[16] = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255 }; -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x16_t shuffle) { +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x16_t shuffle) { return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)), vtbl1q_u8(argb, vget_high_u8(shuffle))); } @@ -45,14 +45,15 @@ static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, // 255 = byte will be zeroed static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x8_t shuffle) { +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x8_t shuffle) { return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), vtbl1_u8(vget_high_u8(argb), shuffle)); } #endif // USE_VTBLQ -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { +static void SubtractGreenFromBlueAndRed_NEON(uint32_t* argb_data, + int num_pixels) { const uint32_t* const end = argb_data + (num_pixels & ~3); #ifdef USE_VTBLQ const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); @@ -61,7 +62,7 @@ static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { #endif for (; argb_data < end; argb_data += 4) { const uint8x16_t argb = vld1q_u8((uint8_t*)argb_data); - const uint8x16_t greens = DoGreenShuffle(argb, shuffle); + const uint8x16_t greens = DoGreenShuffle_NEON(argb, shuffle); vst1q_u8((uint8_t*)argb_data, vsubq_u8(argb, greens)); } // fallthrough and finish off with plain-C @@ -71,8 +72,8 @@ static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { //------------------------------------------------------------------------------ // Color Transform -static void TransformColor(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels) { +static void TransformColor_NEON(const VP8LMultipliers* const m, + uint32_t* argb_data, int num_pixels) { // sign-extended multiplying constants, pre-shifted by 6. #define CST(X) (((int16_t)(m->X << 8)) >> 6) const int16_t rb[8] = { @@ -102,7 +103,7 @@ static void TransformColor(const VP8LMultipliers* const m, for (i = 0; i + 4 <= num_pixels; i += 4) { const uint8x16_t in = vld1q_u8((uint8_t*)(argb_data + i)); // 0 g 0 g - const uint8x16_t greens = DoGreenShuffle(in, shuffle); + const uint8x16_t greens = DoGreenShuffle_NEON(in, shuffle); // x dr x db1 const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb); // r 0 b 0 @@ -132,8 +133,8 @@ static void TransformColor(const VP8LMultipliers* const m, extern void VP8LEncDspInitNEON(void); WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitNEON(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; - VP8LTransformColor = TransformColor; + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_NEON; + VP8LTransformColor = TransformColor_NEON; } #else // !WEBP_USE_NEON diff --git a/3rdparty/libwebp/dsp/lossless_enc_sse2.c b/3rdparty/libwebp/src/dsp/lossless_enc_sse2.c similarity index 90% rename from 3rdparty/libwebp/dsp/lossless_enc_sse2.c rename to 3rdparty/libwebp/src/dsp/lossless_enc_sse2.c index 8ad85d94d7..1eaf35ca8e 100644 --- a/3rdparty/libwebp/dsp/lossless_enc_sse2.c +++ b/3rdparty/libwebp/src/dsp/lossless_enc_sse2.c @@ -11,22 +11,23 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE2) #include #include -#include "./lossless.h" -#include "./common_sse2.h" -#include "./lossless_common.h" +#include "src/dsp/lossless.h" +#include "src/dsp/common_sse2.h" +#include "src/dsp/lossless_common.h" // For sign-extended multiplying constants, pre-shifted by 5: -#define CST_5b(X) (((int16_t)((uint16_t)X << 8)) >> 5) +#define CST_5b(X) (((int16_t)((uint16_t)(X) << 8)) >> 5) //------------------------------------------------------------------------------ // Subtract-Green Transform -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { +static void SubtractGreenFromBlueAndRed_SSE2(uint32_t* argb_data, + int num_pixels) { int i; for (i = 0; i + 4 <= num_pixels; i += 4) { const __m128i in = _mm_loadu_si128((__m128i*)&argb_data[i]); // argb @@ -45,8 +46,8 @@ static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { //------------------------------------------------------------------------------ // Color Transform -static void TransformColor(const VP8LMultipliers* const m, - uint32_t* argb_data, int num_pixels) { +static void TransformColor_SSE2(const VP8LMultipliers* const m, + uint32_t* argb_data, int num_pixels) { const __m128i mults_rb = _mm_set_epi16( CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_), CST_5b(m->green_to_red_), CST_5b(m->green_to_blue_), @@ -80,10 +81,10 @@ static void TransformColor(const VP8LMultipliers* const m, //------------------------------------------------------------------------------ #define SPAN 8 -static void CollectColorBlueTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_blue, int red_to_blue, - int histo[]) { +static void CollectColorBlueTransforms_SSE2(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_blue, int red_to_blue, + int histo[]) { const __m128i mults_r = _mm_set_epi16( CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0, CST_5b(red_to_blue), 0); @@ -131,9 +132,9 @@ static void CollectColorBlueTransforms(const uint32_t* argb, int stride, } } -static void CollectColorRedTransforms(const uint32_t* argb, int stride, - int tile_width, int tile_height, - int green_to_red, int histo[]) { +static void CollectColorRedTransforms_SSE2(const uint32_t* argb, int stride, + int tile_width, int tile_height, + int green_to_red, int histo[]) { const __m128i mults_g = _mm_set_epi16( 0, CST_5b(green_to_red), 0, CST_5b(green_to_red), 0, CST_5b(green_to_red), 0, CST_5b(green_to_red)); @@ -177,8 +178,8 @@ static void CollectColorRedTransforms(const uint32_t* argb, int stride, //------------------------------------------------------------------------------ #define LINE_SIZE 16 // 8 or 16 -static void AddVector(const uint32_t* a, const uint32_t* b, uint32_t* out, - int size) { +static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out, + int size) { int i; assert(size % LINE_SIZE == 0); for (i = 0; i < size; i += LINE_SIZE) { @@ -203,7 +204,7 @@ static void AddVector(const uint32_t* a, const uint32_t* b, uint32_t* out, } } -static void AddVectorEq(const uint32_t* a, uint32_t* out, int size) { +static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) { int i; assert(size % LINE_SIZE == 0); for (i = 0; i < size; i += LINE_SIZE) { @@ -231,22 +232,22 @@ static void AddVectorEq(const uint32_t* a, uint32_t* out, int size) { // Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But // that's ok since the histogram values are less than 1<<28 (max picture size). -static void HistogramAdd(const VP8LHistogram* const a, - const VP8LHistogram* const b, - VP8LHistogram* const out) { +static void HistogramAdd_SSE2(const VP8LHistogram* const a, + const VP8LHistogram* const b, + VP8LHistogram* const out) { int i; const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_); assert(a->palette_code_bits_ == b->palette_code_bits_); if (b != out) { - AddVector(a->literal_, b->literal_, out->literal_, NUM_LITERAL_CODES); - AddVector(a->red_, b->red_, out->red_, NUM_LITERAL_CODES); - AddVector(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES); - AddVector(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES); + AddVector_SSE2(a->literal_, b->literal_, out->literal_, NUM_LITERAL_CODES); + AddVector_SSE2(a->red_, b->red_, out->red_, NUM_LITERAL_CODES); + AddVector_SSE2(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES); + AddVector_SSE2(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES); } else { - AddVectorEq(a->literal_, out->literal_, NUM_LITERAL_CODES); - AddVectorEq(a->red_, out->red_, NUM_LITERAL_CODES); - AddVectorEq(a->blue_, out->blue_, NUM_LITERAL_CODES); - AddVectorEq(a->alpha_, out->alpha_, NUM_LITERAL_CODES); + AddVectorEq_SSE2(a->literal_, out->literal_, NUM_LITERAL_CODES); + AddVectorEq_SSE2(a->red_, out->red_, NUM_LITERAL_CODES); + AddVectorEq_SSE2(a->blue_, out->blue_, NUM_LITERAL_CODES); + AddVectorEq_SSE2(a->alpha_, out->alpha_, NUM_LITERAL_CODES); } for (i = NUM_LITERAL_CODES; i < literal_size; ++i) { out->literal_[i] = a->literal_[i] + b->literal_[i]; @@ -261,9 +262,9 @@ static void HistogramAdd(const VP8LHistogram* const a, // Checks whether the X or Y contribution is worth computing and adding. // Used in loop unrolling. -#define ANALYZE_X_OR_Y(x_or_y, j) \ - do { \ - if (x_or_y[i + j] != 0) retval -= VP8LFastSLog2(x_or_y[i + j]); \ +#define ANALYZE_X_OR_Y(x_or_y, j) \ + do { \ + if ((x_or_y)[i + (j)] != 0) retval -= VP8LFastSLog2((x_or_y)[i + (j)]); \ } while (0) // Checks whether the X + Y contribution is worth computing and adding. @@ -276,7 +277,7 @@ static void HistogramAdd(const VP8LHistogram* const a, } \ } while (0) -static float CombinedShannonEntropy(const int X[256], const int Y[256]) { +static float CombinedShannonEntropy_SSE2(const int X[256], const int Y[256]) { int i; double retval = 0.; int sumX, sumXY; @@ -332,8 +333,8 @@ static float CombinedShannonEntropy(const int X[256], const int Y[256]) { //------------------------------------------------------------------------------ -static int VectorMismatch(const uint32_t* const array1, - const uint32_t* const array2, int length) { +static int VectorMismatch_SSE2(const uint32_t* const array1, + const uint32_t* const array2, int length) { int match_len; if (length >= 12) { @@ -574,8 +575,8 @@ static void PredictorSub10_SSE2(const uint32_t* in, const uint32_t* upper, } // Predictor11: select. -static void GetSumAbsDiff32(const __m128i* const A, const __m128i* const B, - __m128i* const out) { +static void GetSumAbsDiff32_SSE2(const __m128i* const A, const __m128i* const B, + __m128i* const out) { // We can unpack with any value on the upper 32 bits, provided it's the same // on both operands (to that their sum of abs diff is zero). Here we use *A. const __m128i A_lo = _mm_unpacklo_epi32(*A, *A); @@ -596,8 +597,8 @@ static void PredictorSub11_SSE2(const uint32_t* in, const uint32_t* upper, const __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); const __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); __m128i pa, pb; - GetSumAbsDiff32(&T, &TL, &pa); // pa = sum |T-TL| - GetSumAbsDiff32(&L, &TL, &pb); // pb = sum |L-TL| + GetSumAbsDiff32_SSE2(&T, &TL, &pa); // pa = sum |T-TL| + GetSumAbsDiff32_SSE2(&L, &TL, &pb); // pb = sum |L-TL| { const __m128i mask = _mm_cmpgt_epi32(pb, pa); const __m128i A = _mm_and_si128(mask, L); @@ -677,13 +678,13 @@ static void PredictorSub13_SSE2(const uint32_t* in, const uint32_t* upper, extern void VP8LEncDspInitSSE2(void); WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; - VP8LTransformColor = TransformColor; - VP8LCollectColorBlueTransforms = CollectColorBlueTransforms; - VP8LCollectColorRedTransforms = CollectColorRedTransforms; - VP8LHistogramAdd = HistogramAdd; - VP8LCombinedShannonEntropy = CombinedShannonEntropy; - VP8LVectorMismatch = VectorMismatch; + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_SSE2; + VP8LTransformColor = TransformColor_SSE2; + VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE2; + VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE2; + VP8LHistogramAdd = HistogramAdd_SSE2; + VP8LCombinedShannonEntropy = CombinedShannonEntropy_SSE2; + VP8LVectorMismatch = VectorMismatch_SSE2; VP8LBundleColorMap = BundleColorMap_SSE2; VP8LPredictorsSub[0] = PredictorSub0_SSE2; diff --git a/3rdparty/libwebp/dsp/lossless_enc_sse41.c b/3rdparty/libwebp/src/dsp/lossless_enc_sse41.c similarity index 86% rename from 3rdparty/libwebp/dsp/lossless_enc_sse41.c rename to 3rdparty/libwebp/src/dsp/lossless_enc_sse41.c index 821057ccd4..3526a342d3 100644 --- a/3rdparty/libwebp/dsp/lossless_enc_sse41.c +++ b/3rdparty/libwebp/src/dsp/lossless_enc_sse41.c @@ -11,17 +11,18 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE41) #include #include -#include "./lossless.h" +#include "src/dsp/lossless.h" //------------------------------------------------------------------------------ // Subtract-Green Transform -static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { +static void SubtractGreenFromBlueAndRed_SSE41(uint32_t* argb_data, + int num_pixels) { int i; const __m128i kCstShuffle = _mm_set_epi8(-1, 13, -1, 13, -1, 9, -1, 9, -1, 5, -1, 5, -1, 1, -1, 1); @@ -43,7 +44,7 @@ static void SubtractGreenFromBlueAndRed(uint32_t* argb_data, int num_pixels) { extern void VP8LEncDspInitSSE41(void); WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE41(void) { - VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed; + VP8LSubtractGreenFromBlueAndRed = SubtractGreenFromBlueAndRed_SSE41; } #else // !WEBP_USE_SSE41 diff --git a/3rdparty/libwebp/dsp/lossless_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/lossless_mips_dsp_r2.c similarity index 91% rename from 3rdparty/libwebp/dsp/lossless_mips_dsp_r2.c rename to 3rdparty/libwebp/src/dsp/lossless_mips_dsp_r2.c index 2984ce8df7..9888854d57 100644 --- a/3rdparty/libwebp/dsp/lossless_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/lossless_mips_dsp_r2.c @@ -12,12 +12,12 @@ // Author(s): Djordje Pesut (djordje.pesut@imgtec.com) // Jovan Zelincevic (jovan.zelincevic@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS_DSP_R2) -#include "./lossless.h" -#include "./lossless_common.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" #define MAP_COLOR_FUNCS(FUNC_NAME, TYPE, GET_INDEX, GET_VALUE) \ static void FUNC_NAME(const TYPE* src, \ @@ -86,8 +86,8 @@ static void FUNC_NAME(const TYPE* src, \ } \ } -MAP_COLOR_FUNCS(MapARGB, uint32_t, VP8GetARGBIndex, VP8GetARGBValue) -MAP_COLOR_FUNCS(MapAlpha, uint8_t, VP8GetAlphaIndex, VP8GetAlphaValue) +MAP_COLOR_FUNCS(MapARGB_MIPSdspR2, uint32_t, VP8GetARGBIndex, VP8GetARGBValue) +MAP_COLOR_FUNCS(MapAlpha_MIPSdspR2, uint8_t, VP8GetAlphaIndex, VP8GetAlphaValue) #undef MAP_COLOR_FUNCS @@ -188,48 +188,52 @@ static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, return Average2(Average2(a0, a1), Average2(a2, a3)); } -static uint32_t Predictor5(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor5_MIPSdspR2(uint32_t left, const uint32_t* const top) { return Average3(left, top[0], top[1]); } -static uint32_t Predictor6(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor6_MIPSdspR2(uint32_t left, const uint32_t* const top) { return Average2(left, top[-1]); } -static uint32_t Predictor7(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor7_MIPSdspR2(uint32_t left, const uint32_t* const top) { return Average2(left, top[0]); } -static uint32_t Predictor8(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor8_MIPSdspR2(uint32_t left, const uint32_t* const top) { (void)left; return Average2(top[-1], top[0]); } -static uint32_t Predictor9(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor9_MIPSdspR2(uint32_t left, const uint32_t* const top) { (void)left; return Average2(top[0], top[1]); } -static uint32_t Predictor10(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor10_MIPSdspR2(uint32_t left, + const uint32_t* const top) { return Average4(left, top[-1], top[0], top[1]); } -static uint32_t Predictor11(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor11_MIPSdspR2(uint32_t left, + const uint32_t* const top) { return Select(top[0], left, top[-1]); } -static uint32_t Predictor12(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor12_MIPSdspR2(uint32_t left, + const uint32_t* const top) { return ClampedAddSubtractFull(left, top[0], top[-1]); } -static uint32_t Predictor13(uint32_t left, const uint32_t* const top) { +static uint32_t Predictor13_MIPSdspR2(uint32_t left, + const uint32_t* const top) { return ClampedAddSubtractHalf(left, top[0], top[-1]); } // Add green to blue and red channels (i.e. perform the inverse transform of // 'subtract green'). -static void AddGreenToBlueAndRed(const uint32_t* src, int num_pixels, - uint32_t* dst) { +static void AddGreenToBlueAndRed_MIPSdspR2(const uint32_t* src, int num_pixels, + uint32_t* dst) { uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7; const uint32_t* const p_loop1_end = src + (num_pixels & ~3); const uint32_t* const p_loop2_end = src + num_pixels; @@ -285,9 +289,9 @@ static void AddGreenToBlueAndRed(const uint32_t* src, int num_pixels, ); } -static void TransformColorInverse(const VP8LMultipliers* const m, - const uint32_t* src, int num_pixels, - uint32_t* dst) { +static void TransformColorInverse_MIPSdspR2(const VP8LMultipliers* const m, + const uint32_t* src, int num_pixels, + uint32_t* dst) { int temp0, temp1, temp2, temp3, temp4, temp5; uint32_t argb, argb1, new_red; const uint32_t G_to_R = m->green_to_red_; @@ -356,8 +360,8 @@ static void TransformColorInverse(const VP8LMultipliers* const m, if (num_pixels & 1) VP8LTransformColorInverse_C(m, src, 1, dst); } -static void ConvertBGRAToRGB(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGB_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { int temp0, temp1, temp2, temp3; const uint32_t* const p_loop1_end = src + (num_pixels & ~3); const uint32_t* const p_loop2_end = src + num_pixels; @@ -408,8 +412,8 @@ static void ConvertBGRAToRGB(const uint32_t* src, ); } -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGBA_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { int temp0, temp1, temp2, temp3; const uint32_t* const p_loop1_end = src + (num_pixels & ~3); const uint32_t* const p_loop2_end = src + num_pixels; @@ -458,8 +462,8 @@ static void ConvertBGRAToRGBA(const uint32_t* src, ); } -static void ConvertBGRAToRGBA4444(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGBA4444_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { int temp0, temp1, temp2, temp3, temp4, temp5; const uint32_t* const p_loop1_end = src + (num_pixels & ~3); const uint32_t* const p_loop2_end = src + num_pixels; @@ -492,7 +496,7 @@ static void ConvertBGRAToRGBA4444(const uint32_t* src, "ins %[temp3], %[temp5], 16, 4 \n\t" "addiu %[src], %[src], 16 \n\t" "precr.qb.ph %[temp3], %[temp3], %[temp2] \n\t" -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) "usw %[temp1], 0(%[dst]) \n\t" "usw %[temp3], 4(%[dst]) \n\t" #else @@ -514,7 +518,7 @@ static void ConvertBGRAToRGBA4444(const uint32_t* src, "ins %[temp0], %[temp5], 16, 4 \n\t" "addiu %[src], %[src], 4 \n\t" "precr.qb.ph %[temp0], %[temp0], %[temp0] \n\t" -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) "ush %[temp0], 0(%[dst]) \n\t" #else "wsbh %[temp0], %[temp0] \n\t" @@ -532,8 +536,8 @@ static void ConvertBGRAToRGBA4444(const uint32_t* src, ); } -static void ConvertBGRAToRGB565(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGB565_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { int temp0, temp1, temp2, temp3, temp4, temp5; const uint32_t* const p_loop1_end = src + (num_pixels & ~3); const uint32_t* const p_loop2_end = src + num_pixels; @@ -570,7 +574,7 @@ static void ConvertBGRAToRGB565(const uint32_t* src, "ins %[temp2], %[temp3], 0, 5 \n\t" "addiu %[src], %[src], 16 \n\t" "append %[temp2], %[temp1], 16 \n\t" -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) "usw %[temp0], 0(%[dst]) \n\t" "usw %[temp2], 4(%[dst]) \n\t" #else @@ -592,7 +596,7 @@ static void ConvertBGRAToRGB565(const uint32_t* src, "ins %[temp4], %[temp5], 0, 11 \n\t" "addiu %[src], %[src], 4 \n\t" "ins %[temp4], %[temp0], 0, 5 \n\t" -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) "ush %[temp4], 0(%[dst]) \n\t" #else "wsbh %[temp4], %[temp4] \n\t" @@ -610,8 +614,8 @@ static void ConvertBGRAToRGB565(const uint32_t* src, ); } -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToBGR_MIPSdspR2(const uint32_t* src, + int num_pixels, uint8_t* dst) { int temp0, temp1, temp2, temp3; const uint32_t* const p_loop1_end = src + (num_pixels & ~3); const uint32_t* const p_loop2_end = src + num_pixels; @@ -662,24 +666,27 @@ static void ConvertBGRAToBGR(const uint32_t* src, extern void VP8LDspInitMIPSdspR2(void); WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitMIPSdspR2(void) { - VP8LMapColor32b = MapARGB; - VP8LMapColor8b = MapAlpha; - VP8LPredictors[5] = Predictor5; - VP8LPredictors[6] = Predictor6; - VP8LPredictors[7] = Predictor7; - VP8LPredictors[8] = Predictor8; - VP8LPredictors[9] = Predictor9; - VP8LPredictors[10] = Predictor10; - VP8LPredictors[11] = Predictor11; - VP8LPredictors[12] = Predictor12; - VP8LPredictors[13] = Predictor13; - VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; - VP8LTransformColorInverse = TransformColorInverse; - VP8LConvertBGRAToRGB = ConvertBGRAToRGB; - VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; - VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444; - VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565; - VP8LConvertBGRAToBGR = ConvertBGRAToBGR; + VP8LMapColor32b = MapARGB_MIPSdspR2; + VP8LMapColor8b = MapAlpha_MIPSdspR2; + + VP8LPredictors[5] = Predictor5_MIPSdspR2; + VP8LPredictors[6] = Predictor6_MIPSdspR2; + VP8LPredictors[7] = Predictor7_MIPSdspR2; + VP8LPredictors[8] = Predictor8_MIPSdspR2; + VP8LPredictors[9] = Predictor9_MIPSdspR2; + VP8LPredictors[10] = Predictor10_MIPSdspR2; + VP8LPredictors[11] = Predictor11_MIPSdspR2; + VP8LPredictors[12] = Predictor12_MIPSdspR2; + VP8LPredictors[13] = Predictor13_MIPSdspR2; + + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_MIPSdspR2; + VP8LTransformColorInverse = TransformColorInverse_MIPSdspR2; + + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_MIPSdspR2; + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_MIPSdspR2; + VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444_MIPSdspR2; + VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565_MIPSdspR2; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_MIPSdspR2; } #else // !WEBP_USE_MIPS_DSP_R2 diff --git a/3rdparty/libwebp/dsp/lossless_msa.c b/3rdparty/libwebp/src/dsp/lossless_msa.c similarity index 91% rename from 3rdparty/libwebp/dsp/lossless_msa.c rename to 3rdparty/libwebp/src/dsp/lossless_msa.c index f6dd5649ac..9f5472078d 100644 --- a/3rdparty/libwebp/dsp/lossless_msa.c +++ b/3rdparty/libwebp/src/dsp/lossless_msa.c @@ -11,12 +11,12 @@ // // Author: Prashant Patil (prashant.patil@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MSA) -#include "./lossless.h" -#include "./msa_macro.h" +#include "src/dsp/lossless.h" +#include "src/dsp/msa_macro.h" //------------------------------------------------------------------------------ // Colorspace conversion functions @@ -43,7 +43,7 @@ #define CONVERT8_BGRA_XXX(psrc, pdst, m0, m1) do { \ uint64_t pix_d; \ - v16u8 src0, src1, src2, dst0, dst1; \ + v16u8 src0, src1, src2 = { 0 }, dst0, dst1; \ LD_UB2(psrc, 16, src0, src1); \ VSHF_B2_UB(src0, src1, src1, src2, m0, m1, dst0, dst1); \ ST_UB(dst0, pdst); \ @@ -109,8 +109,8 @@ dst = VSHF_UB(src, t0, mask1); \ } while (0) -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGBA_MSA(const uint32_t* src, + int num_pixels, uint8_t* dst) { int i; const uint8_t* ptemp_src = (const uint8_t*)src; uint8_t* ptemp_dst = (uint8_t*)dst; @@ -150,8 +150,8 @@ static void ConvertBGRAToRGBA(const uint32_t* src, } } -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToBGR_MSA(const uint32_t* src, + int num_pixels, uint8_t* dst) { const uint8_t* ptemp_src = (const uint8_t*)src; uint8_t* ptemp_dst = (uint8_t*)dst; const v16u8 mask0 = { 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, @@ -197,8 +197,8 @@ static void ConvertBGRAToBGR(const uint32_t* src, } } -static void ConvertBGRAToRGB(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGB_MSA(const uint32_t* src, + int num_pixels, uint8_t* dst) { const uint8_t* ptemp_src = (const uint8_t*)src; uint8_t* ptemp_dst = (uint8_t*)dst; const v16u8 mask0 = { 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, @@ -244,8 +244,8 @@ static void ConvertBGRAToRGB(const uint32_t* src, } } -static void AddGreenToBlueAndRed(const uint32_t* const src, int num_pixels, - uint32_t* dst) { +static void AddGreenToBlueAndRed_MSA(const uint32_t* const src, int num_pixels, + uint32_t* dst) { int i; const uint8_t* in = (const uint8_t*)src; uint8_t* out = (uint8_t*)dst; @@ -286,9 +286,9 @@ static void AddGreenToBlueAndRed(const uint32_t* const src, int num_pixels, } } -static void TransformColorInverse(const VP8LMultipliers* const m, - const uint32_t* src, int num_pixels, - uint32_t* dst) { +static void TransformColorInverse_MSA(const VP8LMultipliers* const m, + const uint32_t* src, int num_pixels, + uint32_t* dst) { v16u8 src0, dst0; const v16i8 g2br = (v16i8)__msa_fill_w(m->green_to_blue_ | (m->green_to_red_ << 16)); @@ -341,11 +341,12 @@ static void TransformColorInverse(const VP8LMultipliers* const m, extern void VP8LDspInitMSA(void); WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitMSA(void) { - VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; - VP8LConvertBGRAToBGR = ConvertBGRAToBGR; - VP8LConvertBGRAToRGB = ConvertBGRAToRGB; - VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; - VP8LTransformColorInverse = TransformColorInverse; + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_MSA; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_MSA; + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_MSA; + + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_MSA; + VP8LTransformColorInverse = TransformColorInverse_MSA; } #else // !WEBP_USE_MSA diff --git a/3rdparty/libwebp/dsp/lossless_neon.c b/3rdparty/libwebp/src/dsp/lossless_neon.c similarity index 92% rename from 3rdparty/libwebp/dsp/lossless_neon.c rename to 3rdparty/libwebp/src/dsp/lossless_neon.c index 1145d5fad0..76a1b6f873 100644 --- a/3rdparty/libwebp/dsp/lossless_neon.c +++ b/3rdparty/libwebp/src/dsp/lossless_neon.c @@ -11,14 +11,14 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_NEON) #include -#include "./lossless.h" -#include "./neon.h" +#include "src/dsp/lossless.h" +#include "src/dsp/neon.h" //------------------------------------------------------------------------------ // Colorspace conversion functions @@ -26,8 +26,8 @@ #if !defined(WORK_AROUND_GCC) // gcc 4.6.0 had some trouble (NDK-r9) with this code. We only use it for // gcc-4.8.x at least. -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGBA_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { const uint32_t* const end = src + (num_pixels & ~15); for (; src < end; src += 16) { uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); @@ -41,8 +41,8 @@ static void ConvertBGRAToRGBA(const uint32_t* src, VP8LConvertBGRAToRGBA_C(src, num_pixels & 15, dst); // left-overs } -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToBGR_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { const uint32_t* const end = src + (num_pixels & ~15); for (; src < end; src += 16) { const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); @@ -53,8 +53,8 @@ static void ConvertBGRAToBGR(const uint32_t* src, VP8LConvertBGRAToBGR_C(src, num_pixels & 15, dst); // left-overs } -static void ConvertBGRAToRGB(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGB_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { const uint32_t* const end = src + (num_pixels & ~15); for (; src < end; src += 16) { const uint8x16x4_t pixel = vld4q_u8((uint8_t*)src); @@ -71,8 +71,8 @@ static void ConvertBGRAToRGB(const uint32_t* src, static const uint8_t kRGBAShuffle[8] = { 2, 1, 0, 3, 6, 5, 4, 7 }; -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGBA_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { const uint32_t* const end = src + (num_pixels & ~1); const uint8x8_t shuffle = vld1_u8(kRGBAShuffle); for (; src < end; src += 2) { @@ -89,8 +89,8 @@ static const uint8_t kBGRShuffle[3][8] = { { 21, 22, 24, 25, 26, 28, 29, 30 } }; -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToBGR_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { const uint32_t* const end = src + (num_pixels & ~7); const uint8x8_t shuffle0 = vld1_u8(kBGRShuffle[0]); const uint8x8_t shuffle1 = vld1_u8(kBGRShuffle[1]); @@ -116,8 +116,8 @@ static const uint8_t kRGBShuffle[3][8] = { { 21, 20, 26, 25, 24, 30, 29, 28 } }; -static void ConvertBGRAToRGB(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGB_NEON(const uint32_t* src, + int num_pixels, uint8_t* dst) { const uint32_t* const end = src + (num_pixels & ~7); const uint8x8_t shuffle0 = vld1_u8(kRGBShuffle[0]); const uint8x8_t shuffle1 = vld1_u8(kRGBShuffle[1]); @@ -139,7 +139,6 @@ static void ConvertBGRAToRGB(const uint32_t* src, #endif // !WORK_AROUND_GCC - //------------------------------------------------------------------------------ // Predictor Transform @@ -506,8 +505,8 @@ static const uint8_t kGreenShuffle[16] = { 1, 255, 1, 255, 5, 255, 5, 255, 9, 255, 9, 255, 13, 255, 13, 255 }; -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x16_t shuffle) { +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x16_t shuffle) { return vcombine_u8(vtbl1q_u8(argb, vget_low_u8(shuffle)), vtbl1q_u8(argb, vget_high_u8(shuffle))); } @@ -515,15 +514,15 @@ static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, // 255 = byte will be zeroed static const uint8_t kGreenShuffle[8] = { 1, 255, 1, 255, 5, 255, 5, 255 }; -static WEBP_INLINE uint8x16_t DoGreenShuffle(const uint8x16_t argb, - const uint8x8_t shuffle) { +static WEBP_INLINE uint8x16_t DoGreenShuffle_NEON(const uint8x16_t argb, + const uint8x8_t shuffle) { return vcombine_u8(vtbl1_u8(vget_low_u8(argb), shuffle), vtbl1_u8(vget_high_u8(argb), shuffle)); } #endif // USE_VTBLQ -static void AddGreenToBlueAndRed(const uint32_t* src, int num_pixels, - uint32_t* dst) { +static void AddGreenToBlueAndRed_NEON(const uint32_t* src, int num_pixels, + uint32_t* dst) { const uint32_t* const end = src + (num_pixels & ~3); #ifdef USE_VTBLQ const uint8x16_t shuffle = vld1q_u8(kGreenShuffle); @@ -532,7 +531,7 @@ static void AddGreenToBlueAndRed(const uint32_t* src, int num_pixels, #endif for (; src < end; src += 4, dst += 4) { const uint8x16_t argb = vld1q_u8((const uint8_t*)src); - const uint8x16_t greens = DoGreenShuffle(argb, shuffle); + const uint8x16_t greens = DoGreenShuffle_NEON(argb, shuffle); vst1q_u8((uint8_t*)dst, vaddq_u8(argb, greens)); } // fallthrough and finish off with plain-C @@ -542,9 +541,9 @@ static void AddGreenToBlueAndRed(const uint32_t* src, int num_pixels, //------------------------------------------------------------------------------ // Color Transform -static void TransformColorInverse(const VP8LMultipliers* const m, - const uint32_t* const src, int num_pixels, - uint32_t* dst) { +static void TransformColorInverse_NEON(const VP8LMultipliers* const m, + const uint32_t* const src, + int num_pixels, uint32_t* dst) { // sign-extended multiplying constants, pre-shifted by 6. #define CST(X) (((int16_t)(m->X << 8)) >> 6) const int16_t rb[8] = { @@ -575,7 +574,7 @@ static void TransformColorInverse(const VP8LMultipliers* const m, const uint8x16_t in = vld1q_u8((const uint8_t*)(src + i)); const uint32x4_t a0g0 = vandq_u32(vreinterpretq_u32_u8(in), mask_ag); // 0 g 0 g - const uint8x16_t greens = DoGreenShuffle(in, shuffle); + const uint8x16_t greens = DoGreenShuffle_NEON(in, shuffle); // x dr x db1 const int16x8_t A = vqdmulhq_s16(vreinterpretq_s16_u8(greens), mults_rb); // x r' x b' @@ -627,12 +626,12 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitNEON(void) { VP8LPredictorsAdd[12] = PredictorAdd12_NEON; VP8LPredictorsAdd[13] = PredictorAdd13_NEON; - VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; - VP8LConvertBGRAToBGR = ConvertBGRAToBGR; - VP8LConvertBGRAToRGB = ConvertBGRAToRGB; + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_NEON; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_NEON; + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_NEON; - VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; - VP8LTransformColorInverse = TransformColorInverse; + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_NEON; + VP8LTransformColorInverse = TransformColorInverse_NEON; } #else // !WEBP_USE_NEON diff --git a/3rdparty/libwebp/dsp/lossless_sse2.c b/3rdparty/libwebp/src/dsp/lossless_sse2.c similarity index 75% rename from 3rdparty/libwebp/dsp/lossless_sse2.c rename to 3rdparty/libwebp/src/dsp/lossless_sse2.c index 15aae93869..653b466cd6 100644 --- a/3rdparty/libwebp/dsp/lossless_sse2.c +++ b/3rdparty/libwebp/src/dsp/lossless_sse2.c @@ -11,21 +11,22 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE2) -#include "./common_sse2.h" -#include "./lossless.h" -#include "./lossless_common.h" +#include "src/dsp/common_sse2.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" #include #include //------------------------------------------------------------------------------ // Predictor Transform -static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, - uint32_t c2) { +static WEBP_INLINE uint32_t ClampedAddSubtractFull_SSE2(uint32_t c0, + uint32_t c1, + uint32_t c2) { const __m128i zero = _mm_setzero_si128(); const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero); const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero); @@ -37,8 +38,9 @@ static WEBP_INLINE uint32_t ClampedAddSubtractFull(uint32_t c0, uint32_t c1, return output; } -static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, - uint32_t c2) { +static WEBP_INLINE uint32_t ClampedAddSubtractHalf_SSE2(uint32_t c0, + uint32_t c1, + uint32_t c2) { const __m128i zero = _mm_setzero_si128(); const __m128i C0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c0), zero); const __m128i C1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c1), zero); @@ -55,7 +57,7 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1, return output; } -static WEBP_INLINE uint32_t Select(uint32_t a, uint32_t b, uint32_t c) { +static WEBP_INLINE uint32_t Select_SSE2(uint32_t a, uint32_t b, uint32_t c) { int pa_minus_pb; const __m128i zero = _mm_setzero_si128(); const __m128i A0 = _mm_cvtsi32_si128(a); @@ -88,8 +90,9 @@ static WEBP_INLINE void Average2_m128i(const __m128i* const a0, *avg = _mm_sub_epi8(avg1, one); } -static WEBP_INLINE void Average2_uint32(const uint32_t a0, const uint32_t a1, - __m128i* const avg) { +static WEBP_INLINE void Average2_uint32_SSE2(const uint32_t a0, + const uint32_t a1, + __m128i* const avg) { // (a + b) >> 1 = ((a + b + 1) >> 1) - ((a ^ b) & 1) const __m128i ones = _mm_set1_epi8(1); const __m128i A0 = _mm_cvtsi32_si128(a0); @@ -99,7 +102,7 @@ static WEBP_INLINE void Average2_uint32(const uint32_t a0, const uint32_t a1, *avg = _mm_sub_epi8(avg1, one); } -static WEBP_INLINE __m128i Average2_uint32_16(uint32_t a0, uint32_t a1) { +static WEBP_INLINE __m128i Average2_uint32_16_SSE2(uint32_t a0, uint32_t a1) { const __m128i zero = _mm_setzero_si128(); const __m128i A0 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a0), zero); const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero); @@ -107,15 +110,16 @@ static WEBP_INLINE __m128i Average2_uint32_16(uint32_t a0, uint32_t a1) { return _mm_srli_epi16(sum, 1); } -static WEBP_INLINE uint32_t Average2(uint32_t a0, uint32_t a1) { +static WEBP_INLINE uint32_t Average2_SSE2(uint32_t a0, uint32_t a1) { __m128i output; - Average2_uint32(a0, a1, &output); + Average2_uint32_SSE2(a0, a1, &output); return _mm_cvtsi128_si32(output); } -static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { +static WEBP_INLINE uint32_t Average3_SSE2(uint32_t a0, uint32_t a1, + uint32_t a2) { const __m128i zero = _mm_setzero_si128(); - const __m128i avg1 = Average2_uint32_16(a0, a2); + const __m128i avg1 = Average2_uint32_16_SSE2(a0, a2); const __m128i A1 = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a1), zero); const __m128i sum = _mm_add_epi16(avg1, A1); const __m128i avg2 = _mm_srli_epi16(sum, 1); @@ -124,10 +128,10 @@ static WEBP_INLINE uint32_t Average3(uint32_t a0, uint32_t a1, uint32_t a2) { return output; } -static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, - uint32_t a2, uint32_t a3) { - const __m128i avg1 = Average2_uint32_16(a0, a1); - const __m128i avg2 = Average2_uint32_16(a2, a3); +static WEBP_INLINE uint32_t Average4_SSE2(uint32_t a0, uint32_t a1, + uint32_t a2, uint32_t a3) { + const __m128i avg1 = Average2_uint32_16_SSE2(a0, a1); + const __m128i avg2 = Average2_uint32_16_SSE2(a2, a3); const __m128i sum = _mm_add_epi16(avg2, avg1); const __m128i avg3 = _mm_srli_epi16(sum, 1); const __m128i A0 = _mm_packus_epi16(avg3, avg3); @@ -136,41 +140,41 @@ static WEBP_INLINE uint32_t Average4(uint32_t a0, uint32_t a1, } static uint32_t Predictor5_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average3(left, top[0], top[1]); + const uint32_t pred = Average3_SSE2(left, top[0], top[1]); return pred; } static uint32_t Predictor6_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[-1]); + const uint32_t pred = Average2_SSE2(left, top[-1]); return pred; } static uint32_t Predictor7_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(left, top[0]); + const uint32_t pred = Average2_SSE2(left, top[0]); return pred; } static uint32_t Predictor8_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(top[-1], top[0]); + const uint32_t pred = Average2_SSE2(top[-1], top[0]); (void)left; return pred; } static uint32_t Predictor9_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average2(top[0], top[1]); + const uint32_t pred = Average2_SSE2(top[0], top[1]); (void)left; return pred; } static uint32_t Predictor10_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Average4(left, top[-1], top[0], top[1]); + const uint32_t pred = Average4_SSE2(left, top[-1], top[0], top[1]); return pred; } static uint32_t Predictor11_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = Select(top[0], left, top[-1]); + const uint32_t pred = Select_SSE2(top[0], left, top[-1]); return pred; } static uint32_t Predictor12_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractFull(left, top[0], top[-1]); + const uint32_t pred = ClampedAddSubtractFull_SSE2(left, top[0], top[-1]); return pred; } static uint32_t Predictor13_SSE2(uint32_t left, const uint32_t* const top) { - const uint32_t pred = ClampedAddSubtractHalf(left, top[0], top[-1]); + const uint32_t pred = ClampedAddSubtractHalf_SSE2(left, top[0], top[-1]); return pred; } @@ -272,9 +276,24 @@ GENERATE_PREDICTOR_2(9, upper[i + 1]) #undef GENERATE_PREDICTOR_2 // Predictor10: average of (average of (L,TL), average of (T, TR)). +#define DO_PRED10(OUT) do { \ + __m128i avgLTL, avg; \ + Average2_m128i(&L, &TL, &avgLTL); \ + Average2_m128i(&avgTTR, &avgLTL, &avg); \ + L = _mm_add_epi8(avg, src); \ + out[i + (OUT)] = _mm_cvtsi128_si32(L); \ +} while (0) + +#define DO_PRED10_SHIFT do { \ + /* Rotate the pre-computed values for the next iteration.*/ \ + avgTTR = _mm_srli_si128(avgTTR, 4); \ + TL = _mm_srli_si128(TL, 4); \ + src = _mm_srli_si128(src, 4); \ +} while (0) + static void PredictorAdd10_SSE2(const uint32_t* in, const uint32_t* upper, int num_pixels, uint32_t* out) { - int i, j; + int i; __m128i L = _mm_cvtsi32_si128(out[-1]); for (i = 0; i + 4 <= num_pixels; i += 4) { __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); @@ -283,79 +302,90 @@ static void PredictorAdd10_SSE2(const uint32_t* in, const uint32_t* upper, const __m128i TR = _mm_loadu_si128((const __m128i*)&upper[i + 1]); __m128i avgTTR; Average2_m128i(&T, &TR, &avgTTR); - for (j = 0; j < 4; ++j) { - __m128i avgLTL, avg; - Average2_m128i(&L, &TL, &avgLTL); - Average2_m128i(&avgTTR, &avgLTL, &avg); - L = _mm_add_epi8(avg, src); - out[i + j] = _mm_cvtsi128_si32(L); - // Rotate the pre-computed values for the next iteration. - avgTTR = _mm_srli_si128(avgTTR, 4); - TL = _mm_srli_si128(TL, 4); - src = _mm_srli_si128(src, 4); - } + DO_PRED10(0); + DO_PRED10_SHIFT; + DO_PRED10(1); + DO_PRED10_SHIFT; + DO_PRED10(2); + DO_PRED10_SHIFT; + DO_PRED10(3); } if (i != num_pixels) { VP8LPredictorsAdd_C[10](in + i, upper + i, num_pixels - i, out + i); } } +#undef DO_PRED10 +#undef DO_PRED10_SHIFT // Predictor11: select. -static void GetSumAbsDiff32(const __m128i* const A, const __m128i* const B, - __m128i* const out) { - // We can unpack with any value on the upper 32 bits, provided it's the same - // on both operands (to that their sum of abs diff is zero). Here we use *A. - const __m128i A_lo = _mm_unpacklo_epi32(*A, *A); - const __m128i B_lo = _mm_unpacklo_epi32(*B, *A); - const __m128i A_hi = _mm_unpackhi_epi32(*A, *A); - const __m128i B_hi = _mm_unpackhi_epi32(*B, *A); - const __m128i s_lo = _mm_sad_epu8(A_lo, B_lo); - const __m128i s_hi = _mm_sad_epu8(A_hi, B_hi); - *out = _mm_packs_epi32(s_lo, s_hi); -} +#define DO_PRED11(OUT) do { \ + const __m128i L_lo = _mm_unpacklo_epi32(L, T); \ + const __m128i TL_lo = _mm_unpacklo_epi32(TL, T); \ + const __m128i pb = _mm_sad_epu8(L_lo, TL_lo); /* pb = sum |L-TL|*/ \ + const __m128i mask = _mm_cmpgt_epi32(pb, pa); \ + const __m128i A = _mm_and_si128(mask, L); \ + const __m128i B = _mm_andnot_si128(mask, T); \ + const __m128i pred = _mm_or_si128(A, B); /* pred = (pa > b)? L : T*/ \ + L = _mm_add_epi8(src, pred); \ + out[i + (OUT)] = _mm_cvtsi128_si32(L); \ +} while (0) + +#define DO_PRED11_SHIFT do { \ + /* Shift the pre-computed value for the next iteration.*/ \ + T = _mm_srli_si128(T, 4); \ + TL = _mm_srli_si128(TL, 4); \ + src = _mm_srli_si128(src, 4); \ + pa = _mm_srli_si128(pa, 4); \ +} while (0) static void PredictorAdd11_SSE2(const uint32_t* in, const uint32_t* upper, int num_pixels, uint32_t* out) { - int i, j; + int i; + __m128i pa; __m128i L = _mm_cvtsi32_si128(out[-1]); for (i = 0; i + 4 <= num_pixels; i += 4) { __m128i T = _mm_loadu_si128((const __m128i*)&upper[i]); __m128i TL = _mm_loadu_si128((const __m128i*)&upper[i - 1]); __m128i src = _mm_loadu_si128((const __m128i*)&in[i]); - __m128i pa; - GetSumAbsDiff32(&T, &TL, &pa); // pa = sum |T-TL| - for (j = 0; j < 4; ++j) { - const __m128i L_lo = _mm_unpacklo_epi32(L, L); - const __m128i TL_lo = _mm_unpacklo_epi32(TL, L); - const __m128i pb = _mm_sad_epu8(L_lo, TL_lo); // pb = sum |L-TL| - const __m128i mask = _mm_cmpgt_epi32(pb, pa); - const __m128i A = _mm_and_si128(mask, L); - const __m128i B = _mm_andnot_si128(mask, T); - const __m128i pred = _mm_or_si128(A, B); // pred = (L > T)? L : T - L = _mm_add_epi8(src, pred); - out[i + j] = _mm_cvtsi128_si32(L); - // Shift the pre-computed value for the next iteration. - T = _mm_srli_si128(T, 4); - TL = _mm_srli_si128(TL, 4); - src = _mm_srli_si128(src, 4); - pa = _mm_srli_si128(pa, 4); + { + // We can unpack with any value on the upper 32 bits, provided it's the + // same on both operands (so that their sum of abs diff is zero). Here we + // use T. + const __m128i T_lo = _mm_unpacklo_epi32(T, T); + const __m128i TL_lo = _mm_unpacklo_epi32(TL, T); + const __m128i T_hi = _mm_unpackhi_epi32(T, T); + const __m128i TL_hi = _mm_unpackhi_epi32(TL, T); + const __m128i s_lo = _mm_sad_epu8(T_lo, TL_lo); + const __m128i s_hi = _mm_sad_epu8(T_hi, TL_hi); + pa = _mm_packs_epi32(s_lo, s_hi); // pa = sum |T-TL| } + DO_PRED11(0); + DO_PRED11_SHIFT; + DO_PRED11(1); + DO_PRED11_SHIFT; + DO_PRED11(2); + DO_PRED11_SHIFT; + DO_PRED11(3); } if (i != num_pixels) { VP8LPredictorsAdd_C[11](in + i, upper + i, num_pixels - i, out + i); } } +#undef DO_PRED11 +#undef DO_PRED11_SHIFT // Predictor12: ClampedAddSubtractFull. -#define DO_PRED12(DIFF, LANE, OUT) \ -do { \ - const __m128i all = _mm_add_epi16(L, (DIFF)); \ - const __m128i alls = _mm_packus_epi16(all, all); \ - const __m128i res = _mm_add_epi8(src, alls); \ - out[i + (OUT)] = _mm_cvtsi128_si32(res); \ - L = _mm_unpacklo_epi8(res, zero); \ +#define DO_PRED12(DIFF, LANE, OUT) do { \ + const __m128i all = _mm_add_epi16(L, (DIFF)); \ + const __m128i alls = _mm_packus_epi16(all, all); \ + const __m128i res = _mm_add_epi8(src, alls); \ + out[i + (OUT)] = _mm_cvtsi128_si32(res); \ + L = _mm_unpacklo_epi8(res, zero); \ +} while (0) + +#define DO_PRED12_SHIFT(DIFF, LANE) do { \ /* Shift the pre-computed value for the next iteration.*/ \ - if (LANE == 0) (DIFF) = _mm_srli_si128((DIFF), 8); \ + if ((LANE) == 0) (DIFF) = _mm_srli_si128((DIFF), 8); \ src = _mm_srli_si128(src, 4); \ } while (0) @@ -377,8 +407,11 @@ static void PredictorAdd12_SSE2(const uint32_t* in, const uint32_t* upper, __m128i diff_lo = _mm_sub_epi16(T_lo, TL_lo); __m128i diff_hi = _mm_sub_epi16(T_hi, TL_hi); DO_PRED12(diff_lo, 0, 0); + DO_PRED12_SHIFT(diff_lo, 0); DO_PRED12(diff_lo, 1, 1); + DO_PRED12_SHIFT(diff_lo, 1); DO_PRED12(diff_hi, 0, 2); + DO_PRED12_SHIFT(diff_hi, 0); DO_PRED12(diff_hi, 1, 3); } if (i != num_pixels) { @@ -386,6 +419,7 @@ static void PredictorAdd12_SSE2(const uint32_t* in, const uint32_t* upper, } } #undef DO_PRED12 +#undef DO_PRED12_SHIFT // Due to averages with integers, values cannot be accumulated in parallel for // predictors 13. @@ -394,8 +428,8 @@ GENERATE_PREDICTOR_ADD(Predictor13_SSE2, PredictorAdd13_SSE2) //------------------------------------------------------------------------------ // Subtract-Green Transform -static void AddGreenToBlueAndRed(const uint32_t* const src, int num_pixels, - uint32_t* dst) { +static void AddGreenToBlueAndRed_SSE2(const uint32_t* const src, int num_pixels, + uint32_t* dst) { int i; for (i = 0; i + 4 <= num_pixels; i += 4) { const __m128i in = _mm_loadu_si128((const __m128i*)&src[i]); // argb @@ -414,9 +448,9 @@ static void AddGreenToBlueAndRed(const uint32_t* const src, int num_pixels, //------------------------------------------------------------------------------ // Color Transform -static void TransformColorInverse(const VP8LMultipliers* const m, - const uint32_t* const src, int num_pixels, - uint32_t* dst) { +static void TransformColorInverse_SSE2(const VP8LMultipliers* const m, + const uint32_t* const src, + int num_pixels, uint32_t* dst) { // sign-extended multiplying constants, pre-shifted by 5. #define CST(X) (((int16_t)(m->X << 8)) >> 5) // sign-extend const __m128i mults_rb = _mm_set_epi16( @@ -454,8 +488,8 @@ static void TransformColorInverse(const VP8LMultipliers* const m, //------------------------------------------------------------------------------ // Color-space conversion functions -static void ConvertBGRAToRGB(const uint32_t* src, int num_pixels, - uint8_t* dst) { +static void ConvertBGRAToRGB_SSE2(const uint32_t* src, int num_pixels, + uint8_t* dst) { const __m128i* in = (const __m128i*)src; __m128i* out = (__m128i*)dst; @@ -490,27 +524,26 @@ static void ConvertBGRAToRGB(const uint32_t* src, int num_pixels, } } -static void ConvertBGRAToRGBA(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGBA_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { + const __m128i red_blue_mask = _mm_set1_epi32(0x00ff00ffu); const __m128i* in = (const __m128i*)src; __m128i* out = (__m128i*)dst; while (num_pixels >= 8) { - const __m128i bgra0 = _mm_loadu_si128(in++); // bgra0|bgra1|bgra2|bgra3 - const __m128i bgra4 = _mm_loadu_si128(in++); // bgra4|bgra5|bgra6|bgra7 - const __m128i v0l = _mm_unpacklo_epi8(bgra0, bgra4); // b0b4g0g4r0r4a0a4... - const __m128i v0h = _mm_unpackhi_epi8(bgra0, bgra4); // b2b6g2g6r2r6a2a6... - const __m128i v1l = _mm_unpacklo_epi8(v0l, v0h); // b0b2b4b6g0g2g4g6... - const __m128i v1h = _mm_unpackhi_epi8(v0l, v0h); // b1b3b5b7g1g3g5g7... - const __m128i v2l = _mm_unpacklo_epi8(v1l, v1h); // b0...b7 | g0...g7 - const __m128i v2h = _mm_unpackhi_epi8(v1l, v1h); // r0...r7 | a0...a7 - const __m128i ga0 = _mm_unpackhi_epi64(v2l, v2h); // g0...g7 | a0...a7 - const __m128i rb0 = _mm_unpacklo_epi64(v2h, v2l); // r0...r7 | b0...b7 - const __m128i rg0 = _mm_unpacklo_epi8(rb0, ga0); // r0g0r1g1 ... r6g6r7g7 - const __m128i ba0 = _mm_unpackhi_epi8(rb0, ga0); // b0a0b1a1 ... b6a6b7a7 - const __m128i rgba0 = _mm_unpacklo_epi16(rg0, ba0); // rgba0|rgba1... - const __m128i rgba4 = _mm_unpackhi_epi16(rg0, ba0); // rgba4|rgba5... - _mm_storeu_si128(out++, rgba0); - _mm_storeu_si128(out++, rgba4); + const __m128i A1 = _mm_loadu_si128(in++); + const __m128i A2 = _mm_loadu_si128(in++); + const __m128i B1 = _mm_and_si128(A1, red_blue_mask); // R 0 B 0 + const __m128i B2 = _mm_and_si128(A2, red_blue_mask); // R 0 B 0 + const __m128i C1 = _mm_andnot_si128(red_blue_mask, A1); // 0 G 0 A + const __m128i C2 = _mm_andnot_si128(red_blue_mask, A2); // 0 G 0 A + const __m128i D1 = _mm_shufflelo_epi16(B1, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i D2 = _mm_shufflelo_epi16(B2, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i E1 = _mm_shufflehi_epi16(D1, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i E2 = _mm_shufflehi_epi16(D2, _MM_SHUFFLE(2, 3, 0, 1)); + const __m128i F1 = _mm_or_si128(E1, C1); + const __m128i F2 = _mm_or_si128(E2, C2); + _mm_storeu_si128(out++, F1); + _mm_storeu_si128(out++, F2); num_pixels -= 8; } // left-overs @@ -519,8 +552,8 @@ static void ConvertBGRAToRGBA(const uint32_t* src, } } -static void ConvertBGRAToRGBA4444(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGBA4444_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { const __m128i mask_0x0f = _mm_set1_epi8(0x0f); const __m128i mask_0xf0 = _mm_set1_epi8(0xf0); const __m128i* in = (const __m128i*)src; @@ -541,7 +574,7 @@ static void ConvertBGRAToRGBA4444(const uint32_t* src, const __m128i ga2 = _mm_and_si128(ga1, mask_0x0f); // g0-|g1-|...|a6-|a7- const __m128i rgba0 = _mm_or_si128(ga2, rb1); // rg0..rg7 | ba0..ba7 const __m128i rgba1 = _mm_srli_si128(rgba0, 8); // ba0..ba7 | 0 -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) const __m128i rgba = _mm_unpacklo_epi8(rgba1, rgba0); // barg0...barg7 #else const __m128i rgba = _mm_unpacklo_epi8(rgba0, rgba1); // rgba0...rgba7 @@ -555,8 +588,8 @@ static void ConvertBGRAToRGBA4444(const uint32_t* src, } } -static void ConvertBGRAToRGB565(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToRGB565_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { const __m128i mask_0xe0 = _mm_set1_epi8(0xe0); const __m128i mask_0xf8 = _mm_set1_epi8(0xf8); const __m128i mask_0x07 = _mm_set1_epi8(0x07); @@ -582,7 +615,7 @@ static void ConvertBGRAToRGB565(const uint32_t* src, const __m128i rg1 = _mm_or_si128(rb1, g_lo2); // gr0...gr7|xx const __m128i b1 = _mm_srli_epi16(b0, 3); const __m128i gb1 = _mm_or_si128(b1, g_hi2); // bg0...bg7|xx -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) const __m128i rgba = _mm_unpacklo_epi8(gb1, rg1); // rggb0...rggb7 #else const __m128i rgba = _mm_unpacklo_epi8(rg1, gb1); // bgrb0...bgrb7 @@ -596,8 +629,8 @@ static void ConvertBGRAToRGB565(const uint32_t* src, } } -static void ConvertBGRAToBGR(const uint32_t* src, - int num_pixels, uint8_t* dst) { +static void ConvertBGRAToBGR_SSE2(const uint32_t* src, + int num_pixels, uint8_t* dst) { const __m128i mask_l = _mm_set_epi32(0, 0x00ffffff, 0, 0x00ffffff); const __m128i mask_h = _mm_set_epi32(0x00ffffff, 0, 0x00ffffff, 0); const __m128i* in = (const __m128i*)src; @@ -660,14 +693,14 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LDspInitSSE2(void) { VP8LPredictorsAdd[12] = PredictorAdd12_SSE2; VP8LPredictorsAdd[13] = PredictorAdd13_SSE2; - VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed; - VP8LTransformColorInverse = TransformColorInverse; + VP8LAddGreenToBlueAndRed = AddGreenToBlueAndRed_SSE2; + VP8LTransformColorInverse = TransformColorInverse_SSE2; - VP8LConvertBGRAToRGB = ConvertBGRAToRGB; - VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA; - VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444; - VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565; - VP8LConvertBGRAToBGR = ConvertBGRAToBGR; + VP8LConvertBGRAToRGB = ConvertBGRAToRGB_SSE2; + VP8LConvertBGRAToRGBA = ConvertBGRAToRGBA_SSE2; + VP8LConvertBGRAToRGBA4444 = ConvertBGRAToRGBA4444_SSE2; + VP8LConvertBGRAToRGB565 = ConvertBGRAToRGB565_SSE2; + VP8LConvertBGRAToBGR = ConvertBGRAToBGR_SSE2; } #else // !WEBP_USE_SSE2 diff --git a/3rdparty/libwebp/dsp/mips_macro.h b/3rdparty/libwebp/src/dsp/mips_macro.h similarity index 100% rename from 3rdparty/libwebp/dsp/mips_macro.h rename to 3rdparty/libwebp/src/dsp/mips_macro.h diff --git a/3rdparty/libwebp/dsp/msa_macro.h b/3rdparty/libwebp/src/dsp/msa_macro.h similarity index 99% rename from 3rdparty/libwebp/dsp/msa_macro.h rename to 3rdparty/libwebp/src/dsp/msa_macro.h index d0e5f45e01..dfacda6ccd 100644 --- a/3rdparty/libwebp/dsp/msa_macro.h +++ b/3rdparty/libwebp/src/dsp/msa_macro.h @@ -22,6 +22,7 @@ #endif #ifdef CLANG_BUILD + #define ALPHAVAL (-1) #define ADDVI_H(a, b) __msa_addvi_h((v8i16)a, b) #define ADDVI_W(a, b) __msa_addvi_w((v4i32)a, b) #define SRAI_B(a, b) __msa_srai_b((v16i8)a, b) @@ -32,6 +33,7 @@ #define ANDI_B(a, b) __msa_andi_b((v16u8)a, b) #define ORI_B(a, b) __msa_ori_b((v16u8)a, b) #else + #define ALPHAVAL (0xff) #define ADDVI_H(a, b) (a + b) #define ADDVI_W(a, b) (a + b) #define SRAI_B(a, b) (a >> b) diff --git a/3rdparty/libwebp/dsp/neon.h b/3rdparty/libwebp/src/dsp/neon.h similarity index 91% rename from 3rdparty/libwebp/dsp/neon.h rename to 3rdparty/libwebp/src/dsp/neon.h index 3b548a6855..aa1dea1301 100644 --- a/3rdparty/libwebp/dsp/neon.h +++ b/3rdparty/libwebp/src/dsp/neon.h @@ -14,11 +14,12 @@ #include -#include "./dsp.h" +#include "src/dsp/dsp.h" // Right now, some intrinsics functions seem slower, so we disable them -// everywhere except aarch64 where the inline assembly is incompatible. -#if defined(__aarch64__) +// everywhere except newer clang/gcc or aarch64 where the inline assembly is +// incompatible. +#if LOCAL_CLANG_PREREQ(3,8) || LOCAL_GCC_PREREQ(4,9) || defined(__aarch64__) #define WEBP_USE_INTRINSICS // use intrinsics when possible #endif @@ -43,11 +44,11 @@ // if using intrinsics, this flag avoids some functions that make gcc-4.6.3 // crash ("internal compiler error: in immed_double_const, at emit-rtl."). // (probably similar to gcc.gnu.org/bugzilla/show_bug.cgi?id=48183) -#if !(LOCAL_GCC_PREREQ(4,8) || defined(__aarch64__)) +#if !(LOCAL_CLANG_PREREQ(3,8) || LOCAL_GCC_PREREQ(4,8) || defined(__aarch64__)) #define WORK_AROUND_GCC #endif -static WEBP_INLINE int32x4x4_t Transpose4x4(const int32x4x4_t rows) { +static WEBP_INLINE int32x4x4_t Transpose4x4_NEON(const int32x4x4_t rows) { uint64x2x2_t row01, row23; row01.val[0] = vreinterpretq_u64_s32(rows.val[0]); diff --git a/3rdparty/libwebp/dsp/rescaler.c b/3rdparty/libwebp/src/dsp/rescaler.c similarity index 86% rename from 3rdparty/libwebp/dsp/rescaler.c rename to 3rdparty/libwebp/src/dsp/rescaler.c index 0f54502352..4b6b7834e5 100644 --- a/3rdparty/libwebp/dsp/rescaler.c +++ b/3rdparty/libwebp/src/dsp/rescaler.c @@ -13,8 +13,8 @@ #include -#include "./dsp.h" -#include "../utils/rescaler_utils.h" +#include "src/dsp/dsp.h" +#include "src/utils/rescaler_utils.h" //------------------------------------------------------------------------------ // Implementations of critical functions ImportRow / ExportRow @@ -25,7 +25,8 @@ //------------------------------------------------------------------------------ // Row import -void WebPRescalerImportRowExpandC(WebPRescaler* const wrk, const uint8_t* src) { +void WebPRescalerImportRowExpand_C(WebPRescaler* const wrk, + const uint8_t* src) { const int x_stride = wrk->num_channels; const int x_out_max = wrk->dst_width * wrk->num_channels; int channel; @@ -56,7 +57,8 @@ void WebPRescalerImportRowExpandC(WebPRescaler* const wrk, const uint8_t* src) { } } -void WebPRescalerImportRowShrinkC(WebPRescaler* const wrk, const uint8_t* src) { +void WebPRescalerImportRowShrink_C(WebPRescaler* const wrk, + const uint8_t* src) { const int x_stride = wrk->num_channels; const int x_out_max = wrk->dst_width * wrk->num_channels; int channel; @@ -92,7 +94,7 @@ void WebPRescalerImportRowShrinkC(WebPRescaler* const wrk, const uint8_t* src) { //------------------------------------------------------------------------------ // Row export -void WebPRescalerExportRowExpandC(WebPRescaler* const wrk) { +void WebPRescalerExportRowExpand_C(WebPRescaler* const wrk) { int x_out; uint8_t* const dst = wrk->dst; rescaler_t* const irow = wrk->irow; @@ -123,7 +125,7 @@ void WebPRescalerExportRowExpandC(WebPRescaler* const wrk) { } } -void WebPRescalerExportRowShrinkC(WebPRescaler* const wrk) { +void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) { int x_out; uint8_t* const dst = wrk->dst; rescaler_t* const irow = wrk->irow; @@ -207,11 +209,14 @@ static volatile VP8CPUInfo rescaler_last_cpuinfo_used = WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) { if (rescaler_last_cpuinfo_used == VP8GetCPUInfo) return; +#if !defined(WEBP_REDUCE_SIZE) +#if !WEBP_NEON_OMIT_C_CODE + WebPRescalerExportRowExpand = WebPRescalerExportRowExpand_C; + WebPRescalerExportRowShrink = WebPRescalerExportRowShrink_C; +#endif - WebPRescalerImportRowExpand = WebPRescalerImportRowExpandC; - WebPRescalerImportRowShrink = WebPRescalerImportRowShrinkC; - WebPRescalerExportRowExpand = WebPRescalerExportRowExpandC; - WebPRescalerExportRowShrink = WebPRescalerExportRowShrinkC; + WebPRescalerImportRowExpand = WebPRescalerImportRowExpand_C; + WebPRescalerImportRowShrink = WebPRescalerImportRowShrink_C; if (VP8GetCPUInfo != NULL) { #if defined(WEBP_USE_SSE2) @@ -219,11 +224,6 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) { WebPRescalerDspInitSSE2(); } #endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - WebPRescalerDspInitNEON(); - } -#endif #if defined(WEBP_USE_MIPS32) if (VP8GetCPUInfo(kMIPS32)) { WebPRescalerDspInitMIPS32(); @@ -240,5 +240,18 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInit(void) { } #endif } + +#if defined(WEBP_USE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPRescalerDspInitNEON(); + } +#endif + + assert(WebPRescalerExportRowExpand != NULL); + assert(WebPRescalerExportRowShrink != NULL); + assert(WebPRescalerImportRowExpand != NULL); + assert(WebPRescalerImportRowShrink != NULL); +#endif // WEBP_REDUCE_SIZE rescaler_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/3rdparty/libwebp/dsp/rescaler_mips32.c b/3rdparty/libwebp/src/dsp/rescaler_mips32.c similarity index 94% rename from 3rdparty/libwebp/dsp/rescaler_mips32.c rename to 3rdparty/libwebp/src/dsp/rescaler_mips32.c index e09ad5d19f..542f7e5970 100644 --- a/3rdparty/libwebp/dsp/rescaler_mips32.c +++ b/3rdparty/libwebp/src/dsp/rescaler_mips32.c @@ -11,17 +11,18 @@ // // Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" -#if defined(WEBP_USE_MIPS32) +#if defined(WEBP_USE_MIPS32) && !defined(WEBP_REDUCE_SIZE) #include -#include "../utils/rescaler_utils.h" +#include "src/utils/rescaler_utils.h" //------------------------------------------------------------------------------ // Row import -static void ImportRowShrink(WebPRescaler* const wrk, const uint8_t* src) { +static void ImportRowShrink_MIPS32(WebPRescaler* const wrk, + const uint8_t* src) { const int x_stride = wrk->num_channels; const int x_out_max = wrk->dst_width * wrk->num_channels; const int fx_scale = wrk->fx_scale; @@ -80,7 +81,8 @@ static void ImportRowShrink(WebPRescaler* const wrk, const uint8_t* src) { } } -static void ImportRowExpand(WebPRescaler* const wrk, const uint8_t* src) { +static void ImportRowExpand_MIPS32(WebPRescaler* const wrk, + const uint8_t* src) { const int x_stride = wrk->num_channels; const int x_out_max = wrk->dst_width * wrk->num_channels; const int x_add = wrk->x_add; @@ -144,7 +146,7 @@ static void ImportRowExpand(WebPRescaler* const wrk, const uint8_t* src) { //------------------------------------------------------------------------------ // Row export -static void ExportRowExpand(WebPRescaler* const wrk) { +static void ExportRowExpand_MIPS32(WebPRescaler* const wrk) { uint8_t* dst = wrk->dst; rescaler_t* irow = wrk->irow; const int x_out_max = wrk->dst_width * wrk->num_channels; @@ -207,7 +209,7 @@ static void ExportRowExpand(WebPRescaler* const wrk) { } } -static void ExportRowShrink(WebPRescaler* const wrk) { +static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) { const int x_out_max = wrk->dst_width * wrk->num_channels; uint8_t* dst = wrk->dst; rescaler_t* irow = wrk->irow; @@ -278,10 +280,10 @@ static void ExportRowShrink(WebPRescaler* const wrk) { extern void WebPRescalerDspInitMIPS32(void); WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) { - WebPRescalerImportRowExpand = ImportRowExpand; - WebPRescalerImportRowShrink = ImportRowShrink; - WebPRescalerExportRowExpand = ExportRowExpand; - WebPRescalerExportRowShrink = ExportRowShrink; + WebPRescalerImportRowExpand = ImportRowExpand_MIPS32; + WebPRescalerImportRowShrink = ImportRowShrink_MIPS32; + WebPRescalerExportRowExpand = ExportRowExpand_MIPS32; + WebPRescalerExportRowShrink = ExportRowShrink_MIPS32; } #else // !WEBP_USE_MIPS32 diff --git a/3rdparty/libwebp/dsp/rescaler_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c similarity index 97% rename from 3rdparty/libwebp/dsp/rescaler_mips_dsp_r2.c rename to 3rdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c index 2308d64544..b78aac15e6 100644 --- a/3rdparty/libwebp/dsp/rescaler_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/rescaler_mips_dsp_r2.c @@ -11,12 +11,12 @@ // // Author(s): Djordje Pesut (djordje.pesut@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" -#if defined(WEBP_USE_MIPS_DSP_R2) +#if defined(WEBP_USE_MIPS_DSP_R2) && !defined(WEBP_REDUCE_SIZE) #include -#include "../utils/rescaler_utils.h" +#include "src/utils/rescaler_utils.h" #define ROUNDER (WEBP_RESCALER_ONE >> 1) #define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) @@ -24,7 +24,7 @@ //------------------------------------------------------------------------------ // Row export -static void ExportRowShrink(WebPRescaler* const wrk) { +static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) { int i; const int x_out_max = wrk->dst_width * wrk->num_channels; uint8_t* dst = wrk->dst; @@ -162,7 +162,7 @@ static void ExportRowShrink(WebPRescaler* const wrk) { } } -static void ExportRowExpand(WebPRescaler* const wrk) { +static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) { int i; uint8_t* dst = wrk->dst; rescaler_t* irow = wrk->irow; @@ -303,8 +303,8 @@ static void ExportRowExpand(WebPRescaler* const wrk) { extern void WebPRescalerDspInitMIPSdspR2(void); WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) { - WebPRescalerExportRowExpand = ExportRowExpand; - WebPRescalerExportRowShrink = ExportRowShrink; + WebPRescalerExportRowExpand = ExportRowExpand_MIPSdspR2; + WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2; } #else // !WEBP_USE_MIPS_DSP_R2 diff --git a/3rdparty/libwebp/dsp/rescaler_msa.c b/3rdparty/libwebp/src/dsp/rescaler_msa.c similarity index 97% rename from 3rdparty/libwebp/dsp/rescaler_msa.c rename to 3rdparty/libwebp/src/dsp/rescaler_msa.c index 2c10e55d8c..f3bc99f1cd 100644 --- a/3rdparty/libwebp/dsp/rescaler_msa.c +++ b/3rdparty/libwebp/src/dsp/rescaler_msa.c @@ -11,14 +11,14 @@ // // Author: Prashant Patil (prashant.patil@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" -#if defined(WEBP_USE_MSA) +#if defined(WEBP_USE_MSA) && !defined(WEBP_REDUCE_SIZE) #include -#include "../utils/rescaler_utils.h" -#include "./msa_macro.h" +#include "src/utils/rescaler_utils.h" +#include "src/dsp/msa_macro.h" #define ROUNDER (WEBP_RESCALER_ONE >> 1) #define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) @@ -246,7 +246,7 @@ static WEBP_INLINE void ExportRowExpand_1(const uint32_t* frow, uint32_t* irow, } } -static void RescalerExportRowExpand(WebPRescaler* const wrk) { +static void RescalerExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) { uint8_t* dst = wrk->dst; rescaler_t* irow = wrk->irow; const int x_out_max = wrk->dst_width * wrk->num_channels; @@ -411,7 +411,7 @@ static WEBP_INLINE void ExportRowShrink_1(uint32_t* irow, uint8_t* dst, } } -static void RescalerExportRowShrink(WebPRescaler* const wrk) { +static void RescalerExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) { uint8_t* dst = wrk->dst; rescaler_t* irow = wrk->irow; const int x_out_max = wrk->dst_width * wrk->num_channels; @@ -433,8 +433,8 @@ static void RescalerExportRowShrink(WebPRescaler* const wrk) { extern void WebPRescalerDspInitMSA(void); WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMSA(void) { - WebPRescalerExportRowExpand = RescalerExportRowExpand; - WebPRescalerExportRowShrink = RescalerExportRowShrink; + WebPRescalerExportRowExpand = RescalerExportRowExpand_MIPSdspR2; + WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2; } #else // !WEBP_USE_MSA diff --git a/3rdparty/libwebp/dsp/rescaler_neon.c b/3rdparty/libwebp/src/dsp/rescaler_neon.c similarity index 89% rename from 3rdparty/libwebp/dsp/rescaler_neon.c rename to 3rdparty/libwebp/src/dsp/rescaler_neon.c index b2dd8f30cc..3eff9fbaf4 100644 --- a/3rdparty/libwebp/dsp/rescaler_neon.c +++ b/3rdparty/libwebp/src/dsp/rescaler_neon.c @@ -11,14 +11,14 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" -#if defined(WEBP_USE_NEON) +#if defined(WEBP_USE_NEON) && !defined(WEBP_REDUCE_SIZE) #include #include -#include "./neon.h" -#include "../utils/rescaler_utils.h" +#include "src/dsp/neon.h" +#include "src/utils/rescaler_utils.h" #define ROUNDER (WEBP_RESCALER_ONE >> 1) #define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) @@ -41,9 +41,9 @@ #error "MULT_FIX/WEBP_RESCALER_RFIX need some more work" #endif -static uint32x4_t Interpolate(const rescaler_t* const frow, - const rescaler_t* const irow, - uint32_t A, uint32_t B) { +static uint32x4_t Interpolate_NEON(const rescaler_t* const frow, + const rescaler_t* const irow, + uint32_t A, uint32_t B) { LOAD_32x4(frow, A0); LOAD_32x4(irow, B0); const uint64x2_t C0 = vmull_n_u32(vget_low_u32(A0), A); @@ -56,7 +56,7 @@ static uint32x4_t Interpolate(const rescaler_t* const frow, return E; } -static void RescalerExportRowExpand(WebPRescaler* const wrk) { +static void RescalerExportRowExpand_NEON(WebPRescaler* const wrk) { int x_out; uint8_t* const dst = wrk->dst; rescaler_t* const irow = wrk->irow; @@ -91,9 +91,9 @@ static void RescalerExportRowExpand(WebPRescaler* const wrk) { const uint32_t A = (uint32_t)(WEBP_RESCALER_ONE - B); for (x_out = 0; x_out < max_span; x_out += 8) { const uint32x4_t C0 = - Interpolate(frow + x_out + 0, irow + x_out + 0, A, B); + Interpolate_NEON(frow + x_out + 0, irow + x_out + 0, A, B); const uint32x4_t C1 = - Interpolate(frow + x_out + 4, irow + x_out + 4, A, B); + Interpolate_NEON(frow + x_out + 4, irow + x_out + 4, A, B); const uint32x4_t D0 = MULT_FIX(C0, fy_scale_half); const uint32x4_t D1 = MULT_FIX(C1, fy_scale_half); const uint16x4_t E0 = vmovn_u32(D0); @@ -112,7 +112,7 @@ static void RescalerExportRowExpand(WebPRescaler* const wrk) { } } -static void RescalerExportRowShrink(WebPRescaler* const wrk) { +static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) { int x_out; uint8_t* const dst = wrk->dst; rescaler_t* const irow = wrk->irow; @@ -175,8 +175,8 @@ static void RescalerExportRowShrink(WebPRescaler* const wrk) { extern void WebPRescalerDspInitNEON(void); WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitNEON(void) { - WebPRescalerExportRowExpand = RescalerExportRowExpand; - WebPRescalerExportRowShrink = RescalerExportRowShrink; + WebPRescalerExportRowExpand = RescalerExportRowExpand_NEON; + WebPRescalerExportRowShrink = RescalerExportRowShrink_NEON; } #else // !WEBP_USE_NEON diff --git a/3rdparty/libwebp/dsp/rescaler_sse2.c b/3rdparty/libwebp/src/dsp/rescaler_sse2.c similarity index 81% rename from 3rdparty/libwebp/dsp/rescaler_sse2.c rename to 3rdparty/libwebp/src/dsp/rescaler_sse2.c index 1ea1139660..f93b204fe1 100644 --- a/3rdparty/libwebp/dsp/rescaler_sse2.c +++ b/3rdparty/libwebp/src/dsp/rescaler_sse2.c @@ -11,14 +11,14 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" -#if defined(WEBP_USE_SSE2) +#if defined(WEBP_USE_SSE2) && !defined(WEBP_REDUCE_SIZE) #include #include -#include "../utils/rescaler_utils.h" -#include "../utils/utils.h" +#include "src/utils/rescaler_utils.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // Implementations of critical functions ImportRow / ExportRow @@ -27,7 +27,7 @@ #define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX) // input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0 -static void LoadTwoPixels(const uint8_t* const src, __m128i* out) { +static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) { const __m128i zero = _mm_setzero_si128(); const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH const __m128i B = _mm_unpacklo_epi8(A, zero); // A0B0C0D0E0F0G0H0 @@ -36,14 +36,14 @@ static void LoadTwoPixels(const uint8_t* const src, __m128i* out) { } // input: 8 bytes ABCDEFGH -> output: A0B0C0D0E0F0G0H0 -static void LoadHeightPixels(const uint8_t* const src, __m128i* out) { +static void LoadHeightPixels_SSE2(const uint8_t* const src, __m128i* out) { const __m128i zero = _mm_setzero_si128(); const __m128i A = _mm_loadl_epi64((const __m128i*)(src)); // ABCDEFGH *out = _mm_unpacklo_epi8(A, zero); } -static void RescalerImportRowExpandSSE2(WebPRescaler* const wrk, - const uint8_t* src) { +static void RescalerImportRowExpand_SSE2(WebPRescaler* const wrk, + const uint8_t* src) { rescaler_t* frow = wrk->frow; const rescaler_t* const frow_end = frow + wrk->dst_width * wrk->num_channels; const int x_add = wrk->x_add; @@ -54,10 +54,10 @@ static void RescalerImportRowExpandSSE2(WebPRescaler* const wrk, assert(wrk->x_expand); if (wrk->num_channels == 4) { if (wrk->src_width < 2) { - WebPRescalerImportRowExpandC(wrk, src); + WebPRescalerImportRowExpand_C(wrk, src); return; } - LoadTwoPixels(src, &cur_pixels); + LoadTwoPixels_SSE2(src, &cur_pixels); src += 4; while (1) { const __m128i mult = _mm_set1_epi32(((x_add - accum) << 16) | accum); @@ -67,7 +67,7 @@ static void RescalerImportRowExpandSSE2(WebPRescaler* const wrk, if (frow >= frow_end) break; accum -= wrk->x_sub; if (accum < 0) { - LoadTwoPixels(src, &cur_pixels); + LoadTwoPixels_SSE2(src, &cur_pixels); src += 4; accum += x_add; } @@ -76,10 +76,10 @@ static void RescalerImportRowExpandSSE2(WebPRescaler* const wrk, int left; const uint8_t* const src_limit = src + wrk->src_width - 8; if (wrk->src_width < 8) { - WebPRescalerImportRowExpandC(wrk, src); + WebPRescalerImportRowExpand_C(wrk, src); return; } - LoadHeightPixels(src, &cur_pixels); + LoadHeightPixels_SSE2(src, &cur_pixels); src += 7; left = 7; while (1) { @@ -94,7 +94,7 @@ static void RescalerImportRowExpandSSE2(WebPRescaler* const wrk, if (--left) { cur_pixels = _mm_srli_si128(cur_pixels, 2); } else if (src <= src_limit) { - LoadHeightPixels(src, &cur_pixels); + LoadHeightPixels_SSE2(src, &cur_pixels); src += 7; left = 7; } else { // tail @@ -110,8 +110,8 @@ static void RescalerImportRowExpandSSE2(WebPRescaler* const wrk, assert(accum == 0); } -static void RescalerImportRowShrinkSSE2(WebPRescaler* const wrk, - const uint8_t* src) { +static void RescalerImportRowShrink_SSE2(WebPRescaler* const wrk, + const uint8_t* src) { const int x_sub = wrk->x_sub; int accum = 0; const __m128i zero = _mm_setzero_si128(); @@ -123,7 +123,7 @@ static void RescalerImportRowShrinkSSE2(WebPRescaler* const wrk, const rescaler_t* const frow_end = wrk->frow + 4 * wrk->dst_width; if (wrk->num_channels != 4 || wrk->x_add > (x_sub << 7)) { - WebPRescalerImportRowShrinkC(wrk, src); + WebPRescalerImportRowShrink_C(wrk, src); return; } assert(!WebPRescalerInputDone(wrk)); @@ -169,12 +169,12 @@ static void RescalerImportRowShrinkSSE2(WebPRescaler* const wrk, // Row export // load *src as epi64, multiply by mult and store result in [out0 ... out3] -static WEBP_INLINE void LoadDispatchAndMult(const rescaler_t* const src, - const __m128i* const mult, - __m128i* const out0, - __m128i* const out1, - __m128i* const out2, - __m128i* const out3) { +static WEBP_INLINE void LoadDispatchAndMult_SSE2(const rescaler_t* const src, + const __m128i* const mult, + __m128i* const out0, + __m128i* const out1, + __m128i* const out2, + __m128i* const out3) { const __m128i A0 = _mm_loadu_si128((const __m128i*)(src + 0)); const __m128i A1 = _mm_loadu_si128((const __m128i*)(src + 4)); const __m128i A2 = _mm_srli_epi64(A0, 32); @@ -192,12 +192,12 @@ static WEBP_INLINE void LoadDispatchAndMult(const rescaler_t* const src, } } -static WEBP_INLINE void ProcessRow(const __m128i* const A0, - const __m128i* const A1, - const __m128i* const A2, - const __m128i* const A3, - const __m128i* const mult, - uint8_t* const dst) { +static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0, + const __m128i* const A1, + const __m128i* const A2, + const __m128i* const A3, + const __m128i* const mult, + uint8_t* const dst) { const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0); const __m128i B0 = _mm_mul_epu32(*A0, *mult); @@ -226,7 +226,7 @@ static WEBP_INLINE void ProcessRow(const __m128i* const A0, _mm_storel_epi64((__m128i*)dst, G); } -static void RescalerExportRowExpandSSE2(WebPRescaler* const wrk) { +static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) { int x_out; uint8_t* const dst = wrk->dst; rescaler_t* const irow = wrk->irow; @@ -240,8 +240,8 @@ static void RescalerExportRowExpandSSE2(WebPRescaler* const wrk) { if (wrk->y_accum == 0) { for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { __m128i A0, A1, A2, A3; - LoadDispatchAndMult(frow + x_out, NULL, &A0, &A1, &A2, &A3); - ProcessRow(&A0, &A1, &A2, &A3, &mult, dst + x_out); + LoadDispatchAndMult_SSE2(frow + x_out, NULL, &A0, &A1, &A2, &A3); + ProcessRow_SSE2(&A0, &A1, &A2, &A3, &mult, dst + x_out); } for (; x_out < x_out_max; ++x_out) { const uint32_t J = frow[x_out]; @@ -257,8 +257,8 @@ static void RescalerExportRowExpandSSE2(WebPRescaler* const wrk) { const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { __m128i A0, A1, A2, A3, B0, B1, B2, B3; - LoadDispatchAndMult(frow + x_out, &mA, &A0, &A1, &A2, &A3); - LoadDispatchAndMult(irow + x_out, &mB, &B0, &B1, &B2, &B3); + LoadDispatchAndMult_SSE2(frow + x_out, &mA, &A0, &A1, &A2, &A3); + LoadDispatchAndMult_SSE2(irow + x_out, &mB, &B0, &B1, &B2, &B3); { const __m128i C0 = _mm_add_epi64(A0, B0); const __m128i C1 = _mm_add_epi64(A1, B1); @@ -272,7 +272,7 @@ static void RescalerExportRowExpandSSE2(WebPRescaler* const wrk) { const __m128i E1 = _mm_srli_epi64(D1, WEBP_RESCALER_RFIX); const __m128i E2 = _mm_srli_epi64(D2, WEBP_RESCALER_RFIX); const __m128i E3 = _mm_srli_epi64(D3, WEBP_RESCALER_RFIX); - ProcessRow(&E0, &E1, &E2, &E3, &mult, dst + x_out); + ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult, dst + x_out); } } for (; x_out < x_out_max; ++x_out) { @@ -286,7 +286,7 @@ static void RescalerExportRowExpandSSE2(WebPRescaler* const wrk) { } } -static void RescalerExportRowShrinkSSE2(WebPRescaler* const wrk) { +static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) { int x_out; uint8_t* const dst = wrk->dst; rescaler_t* const irow = wrk->irow; @@ -303,8 +303,8 @@ static void RescalerExportRowShrinkSSE2(WebPRescaler* const wrk) { const __m128i rounder = _mm_set_epi32(0, ROUNDER, 0, ROUNDER); for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { __m128i A0, A1, A2, A3, B0, B1, B2, B3; - LoadDispatchAndMult(irow + x_out, NULL, &A0, &A1, &A2, &A3); - LoadDispatchAndMult(frow + x_out, &mult_y, &B0, &B1, &B2, &B3); + LoadDispatchAndMult_SSE2(irow + x_out, NULL, &A0, &A1, &A2, &A3); + LoadDispatchAndMult_SSE2(frow + x_out, &mult_y, &B0, &B1, &B2, &B3); { const __m128i C0 = _mm_add_epi64(B0, rounder); const __m128i C1 = _mm_add_epi64(B1, rounder); @@ -324,7 +324,7 @@ static void RescalerExportRowShrinkSSE2(WebPRescaler* const wrk) { const __m128i G1 = _mm_or_si128(D1, F3); _mm_storeu_si128((__m128i*)(irow + x_out + 0), G0); _mm_storeu_si128((__m128i*)(irow + x_out + 4), G1); - ProcessRow(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out); + ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out); } } for (; x_out < x_out_max; ++x_out) { @@ -340,10 +340,10 @@ static void RescalerExportRowShrinkSSE2(WebPRescaler* const wrk) { const __m128i zero = _mm_setzero_si128(); for (x_out = 0; x_out + 8 <= x_out_max; x_out += 8) { __m128i A0, A1, A2, A3; - LoadDispatchAndMult(irow + x_out, NULL, &A0, &A1, &A2, &A3); + LoadDispatchAndMult_SSE2(irow + x_out, NULL, &A0, &A1, &A2, &A3); _mm_storeu_si128((__m128i*)(irow + x_out + 0), zero); _mm_storeu_si128((__m128i*)(irow + x_out + 4), zero); - ProcessRow(&A0, &A1, &A2, &A3, &mult, dst + x_out); + ProcessRow_SSE2(&A0, &A1, &A2, &A3, &mult, dst + x_out); } for (; x_out < x_out_max; ++x_out) { const int v = (int)MULT_FIX(irow[x_out], scale); @@ -362,10 +362,10 @@ static void RescalerExportRowShrinkSSE2(WebPRescaler* const wrk) { extern void WebPRescalerDspInitSSE2(void); WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitSSE2(void) { - WebPRescalerImportRowExpand = RescalerImportRowExpandSSE2; - WebPRescalerImportRowShrink = RescalerImportRowShrinkSSE2; - WebPRescalerExportRowExpand = RescalerExportRowExpandSSE2; - WebPRescalerExportRowShrink = RescalerExportRowShrinkSSE2; + WebPRescalerImportRowExpand = RescalerImportRowExpand_SSE2; + WebPRescalerImportRowShrink = RescalerImportRowShrink_SSE2; + WebPRescalerExportRowExpand = RescalerExportRowExpand_SSE2; + WebPRescalerExportRowShrink = RescalerExportRowShrink_SSE2; } #else // !WEBP_USE_SSE2 diff --git a/3rdparty/libwebp/src/dsp/ssim.c b/3rdparty/libwebp/src/dsp/ssim.c new file mode 100644 index 0000000000..dc1b518a33 --- /dev/null +++ b/3rdparty/libwebp/src/dsp/ssim.c @@ -0,0 +1,166 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// distortion calculation +// +// Author: Skal (pascal.massimino@gmail.com) + +#include +#include // for abs() + +#include "src/dsp/dsp.h" + +#if !defined(WEBP_REDUCE_SIZE) + +//------------------------------------------------------------------------------ +// SSIM / PSNR + +// hat-shaped filter. Sum of coefficients is equal to 16. +static const uint32_t kWeight[2 * VP8_SSIM_KERNEL + 1] = { + 1, 2, 3, 4, 3, 2, 1 +}; +static const uint32_t kWeightSum = 16 * 16; // sum{kWeight}^2 + +static WEBP_INLINE double SSIMCalculation( + const VP8DistoStats* const stats, uint32_t N /*num samples*/) { + const uint32_t w2 = N * N; + const uint32_t C1 = 20 * w2; + const uint32_t C2 = 60 * w2; + const uint32_t C3 = 8 * 8 * w2; // 'dark' limit ~= 6 + const uint64_t xmxm = (uint64_t)stats->xm * stats->xm; + const uint64_t ymym = (uint64_t)stats->ym * stats->ym; + if (xmxm + ymym >= C3) { + const int64_t xmym = (int64_t)stats->xm * stats->ym; + const int64_t sxy = (int64_t)stats->xym * N - xmym; // can be negative + const uint64_t sxx = (uint64_t)stats->xxm * N - xmxm; + const uint64_t syy = (uint64_t)stats->yym * N - ymym; + // we descale by 8 to prevent overflow during the fnum/fden multiply. + const uint64_t num_S = (2 * (uint64_t)(sxy < 0 ? 0 : sxy) + C2) >> 8; + const uint64_t den_S = (sxx + syy + C2) >> 8; + const uint64_t fnum = (2 * xmym + C1) * num_S; + const uint64_t fden = (xmxm + ymym + C1) * den_S; + const double r = (double)fnum / fden; + assert(r >= 0. && r <= 1.0); + return r; + } + return 1.; // area is too dark to contribute meaningfully +} + +double VP8SSIMFromStats(const VP8DistoStats* const stats) { + return SSIMCalculation(stats, kWeightSum); +} + +double VP8SSIMFromStatsClipped(const VP8DistoStats* const stats) { + return SSIMCalculation(stats, stats->w); +} + +static double SSIMGetClipped_C(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2, + int xo, int yo, int W, int H) { + VP8DistoStats stats = { 0, 0, 0, 0, 0, 0 }; + const int ymin = (yo - VP8_SSIM_KERNEL < 0) ? 0 : yo - VP8_SSIM_KERNEL; + const int ymax = (yo + VP8_SSIM_KERNEL > H - 1) ? H - 1 + : yo + VP8_SSIM_KERNEL; + const int xmin = (xo - VP8_SSIM_KERNEL < 0) ? 0 : xo - VP8_SSIM_KERNEL; + const int xmax = (xo + VP8_SSIM_KERNEL > W - 1) ? W - 1 + : xo + VP8_SSIM_KERNEL; + int x, y; + src1 += ymin * stride1; + src2 += ymin * stride2; + for (y = ymin; y <= ymax; ++y, src1 += stride1, src2 += stride2) { + for (x = xmin; x <= xmax; ++x) { + const uint32_t w = kWeight[VP8_SSIM_KERNEL + x - xo] + * kWeight[VP8_SSIM_KERNEL + y - yo]; + const uint32_t s1 = src1[x]; + const uint32_t s2 = src2[x]; + stats.w += w; + stats.xm += w * s1; + stats.ym += w * s2; + stats.xxm += w * s1 * s1; + stats.xym += w * s1 * s2; + stats.yym += w * s2 * s2; + } + } + return VP8SSIMFromStatsClipped(&stats); +} + +static double SSIMGet_C(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2) { + VP8DistoStats stats = { 0, 0, 0, 0, 0, 0 }; + int x, y; + for (y = 0; y <= 2 * VP8_SSIM_KERNEL; ++y, src1 += stride1, src2 += stride2) { + for (x = 0; x <= 2 * VP8_SSIM_KERNEL; ++x) { + const uint32_t w = kWeight[x] * kWeight[y]; + const uint32_t s1 = src1[x]; + const uint32_t s2 = src2[x]; + stats.xm += w * s1; + stats.ym += w * s2; + stats.xxm += w * s1 * s1; + stats.xym += w * s1 * s2; + stats.yym += w * s2 * s2; + } + } + return VP8SSIMFromStats(&stats); +} + +#endif // !defined(WEBP_REDUCE_SIZE) + +//------------------------------------------------------------------------------ + +#if !defined(WEBP_DISABLE_STATS) +static uint32_t AccumulateSSE_C(const uint8_t* src1, + const uint8_t* src2, int len) { + int i; + uint32_t sse2 = 0; + assert(len <= 65535); // to ensure that accumulation fits within uint32_t + for (i = 0; i < len; ++i) { + const int32_t diff = src1[i] - src2[i]; + sse2 += diff * diff; + } + return sse2; +} +#endif + +//------------------------------------------------------------------------------ + +#if !defined(WEBP_REDUCE_SIZE) +VP8SSIMGetFunc VP8SSIMGet; +VP8SSIMGetClippedFunc VP8SSIMGetClipped; +#endif +#if !defined(WEBP_DISABLE_STATS) +VP8AccumulateSSEFunc VP8AccumulateSSE; +#endif + +extern void VP8SSIMDspInitSSE2(void); + +static volatile VP8CPUInfo ssim_last_cpuinfo_used = + (VP8CPUInfo)&ssim_last_cpuinfo_used; + +WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInit(void) { + if (ssim_last_cpuinfo_used == VP8GetCPUInfo) return; + +#if !defined(WEBP_REDUCE_SIZE) + VP8SSIMGetClipped = SSIMGetClipped_C; + VP8SSIMGet = SSIMGet_C; +#endif + +#if !defined(WEBP_DISABLE_STATS) + VP8AccumulateSSE = AccumulateSSE_C; +#endif + + if (VP8GetCPUInfo != NULL) { +#if defined(WEBP_USE_SSE2) + if (VP8GetCPUInfo(kSSE2)) { + VP8SSIMDspInitSSE2(); + } +#endif + } + + ssim_last_cpuinfo_used = VP8GetCPUInfo; +} diff --git a/3rdparty/libwebp/src/dsp/ssim_sse2.c b/3rdparty/libwebp/src/dsp/ssim_sse2.c new file mode 100644 index 0000000000..1dcb0eb0ec --- /dev/null +++ b/3rdparty/libwebp/src/dsp/ssim_sse2.c @@ -0,0 +1,165 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// SSE2 version of distortion calculation +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/dsp.h" + +#if defined(WEBP_USE_SSE2) + +#include +#include + +#include "src/dsp/common_sse2.h" + +#if !defined(WEBP_DISABLE_STATS) + +// Helper function +static WEBP_INLINE void SubtractAndSquare_SSE2(const __m128i a, const __m128i b, + __m128i* const sum) { + // take abs(a-b) in 8b + const __m128i a_b = _mm_subs_epu8(a, b); + const __m128i b_a = _mm_subs_epu8(b, a); + const __m128i abs_a_b = _mm_or_si128(a_b, b_a); + // zero-extend to 16b + const __m128i zero = _mm_setzero_si128(); + const __m128i C0 = _mm_unpacklo_epi8(abs_a_b, zero); + const __m128i C1 = _mm_unpackhi_epi8(abs_a_b, zero); + // multiply with self + const __m128i sum1 = _mm_madd_epi16(C0, C0); + const __m128i sum2 = _mm_madd_epi16(C1, C1); + *sum = _mm_add_epi32(sum1, sum2); +} + +//------------------------------------------------------------------------------ +// SSIM / PSNR entry point + +static uint32_t AccumulateSSE_SSE2(const uint8_t* src1, + const uint8_t* src2, int len) { + int i = 0; + uint32_t sse2 = 0; + if (len >= 16) { + const int limit = len - 32; + int32_t tmp[4]; + __m128i sum1; + __m128i sum = _mm_setzero_si128(); + __m128i a0 = _mm_loadu_si128((const __m128i*)&src1[i]); + __m128i b0 = _mm_loadu_si128((const __m128i*)&src2[i]); + i += 16; + while (i <= limit) { + const __m128i a1 = _mm_loadu_si128((const __m128i*)&src1[i]); + const __m128i b1 = _mm_loadu_si128((const __m128i*)&src2[i]); + __m128i sum2; + i += 16; + SubtractAndSquare_SSE2(a0, b0, &sum1); + sum = _mm_add_epi32(sum, sum1); + a0 = _mm_loadu_si128((const __m128i*)&src1[i]); + b0 = _mm_loadu_si128((const __m128i*)&src2[i]); + i += 16; + SubtractAndSquare_SSE2(a1, b1, &sum2); + sum = _mm_add_epi32(sum, sum2); + } + SubtractAndSquare_SSE2(a0, b0, &sum1); + sum = _mm_add_epi32(sum, sum1); + _mm_storeu_si128((__m128i*)tmp, sum); + sse2 += (tmp[3] + tmp[2] + tmp[1] + tmp[0]); + } + + for (; i < len; ++i) { + const int32_t diff = src1[i] - src2[i]; + sse2 += diff * diff; + } + return sse2; +} +#endif // !defined(WEBP_DISABLE_STATS) + +#if !defined(WEBP_REDUCE_SIZE) + +static uint32_t HorizontalAdd16b_SSE2(const __m128i* const m) { + uint16_t tmp[8]; + const __m128i a = _mm_srli_si128(*m, 8); + const __m128i b = _mm_add_epi16(*m, a); + _mm_storeu_si128((__m128i*)tmp, b); + return (uint32_t)tmp[3] + tmp[2] + tmp[1] + tmp[0]; +} + +static uint32_t HorizontalAdd32b_SSE2(const __m128i* const m) { + const __m128i a = _mm_srli_si128(*m, 8); + const __m128i b = _mm_add_epi32(*m, a); + const __m128i c = _mm_add_epi32(b, _mm_srli_si128(b, 4)); + return (uint32_t)_mm_cvtsi128_si32(c); +} + +static const uint16_t kWeight[] = { 1, 2, 3, 4, 3, 2, 1, 0 }; + +#define ACCUMULATE_ROW(WEIGHT) do { \ + /* compute row weight (Wx * Wy) */ \ + const __m128i Wy = _mm_set1_epi16((WEIGHT)); \ + const __m128i W = _mm_mullo_epi16(Wx, Wy); \ + /* process 8 bytes at a time (7 bytes, actually) */ \ + const __m128i a0 = _mm_loadl_epi64((const __m128i*)src1); \ + const __m128i b0 = _mm_loadl_epi64((const __m128i*)src2); \ + /* convert to 16b and multiply by weight */ \ + const __m128i a1 = _mm_unpacklo_epi8(a0, zero); \ + const __m128i b1 = _mm_unpacklo_epi8(b0, zero); \ + const __m128i wa1 = _mm_mullo_epi16(a1, W); \ + const __m128i wb1 = _mm_mullo_epi16(b1, W); \ + /* accumulate */ \ + xm = _mm_add_epi16(xm, wa1); \ + ym = _mm_add_epi16(ym, wb1); \ + xxm = _mm_add_epi32(xxm, _mm_madd_epi16(a1, wa1)); \ + xym = _mm_add_epi32(xym, _mm_madd_epi16(a1, wb1)); \ + yym = _mm_add_epi32(yym, _mm_madd_epi16(b1, wb1)); \ + src1 += stride1; \ + src2 += stride2; \ +} while (0) + +static double SSIMGet_SSE2(const uint8_t* src1, int stride1, + const uint8_t* src2, int stride2) { + VP8DistoStats stats; + const __m128i zero = _mm_setzero_si128(); + __m128i xm = zero, ym = zero; // 16b accums + __m128i xxm = zero, yym = zero, xym = zero; // 32b accum + const __m128i Wx = _mm_loadu_si128((const __m128i*)kWeight); + assert(2 * VP8_SSIM_KERNEL + 1 == 7); + ACCUMULATE_ROW(1); + ACCUMULATE_ROW(2); + ACCUMULATE_ROW(3); + ACCUMULATE_ROW(4); + ACCUMULATE_ROW(3); + ACCUMULATE_ROW(2); + ACCUMULATE_ROW(1); + stats.xm = HorizontalAdd16b_SSE2(&xm); + stats.ym = HorizontalAdd16b_SSE2(&ym); + stats.xxm = HorizontalAdd32b_SSE2(&xxm); + stats.xym = HorizontalAdd32b_SSE2(&xym); + stats.yym = HorizontalAdd32b_SSE2(&yym); + return VP8SSIMFromStats(&stats); +} + +#endif // !defined(WEBP_REDUCE_SIZE) + +extern void VP8SSIMDspInitSSE2(void); + +WEBP_TSAN_IGNORE_FUNCTION void VP8SSIMDspInitSSE2(void) { +#if !defined(WEBP_DISABLE_STATS) + VP8AccumulateSSE = AccumulateSSE_SSE2; +#endif +#if !defined(WEBP_REDUCE_SIZE) + VP8SSIMGet = SSIMGet_SSE2; +#endif +} + +#else // !WEBP_USE_SSE2 + +WEBP_DSP_INIT_STUB(VP8SSIMDspInitSSE2) + +#endif // WEBP_USE_SSE2 diff --git a/3rdparty/libwebp/dsp/upsampling.c b/3rdparty/libwebp/src/dsp/upsampling.c similarity index 68% rename from 3rdparty/libwebp/dsp/upsampling.c rename to 3rdparty/libwebp/src/dsp/upsampling.c index 265e722c10..e72626a82a 100644 --- a/3rdparty/libwebp/dsp/upsampling.c +++ b/3rdparty/libwebp/src/dsp/upsampling.c @@ -11,8 +11,8 @@ // // Author: somnath@google.com (Somnath Banerjee) -#include "./dsp.h" -#include "./yuv.h" +#include "src/dsp/dsp.h" +#include "src/dsp/yuv.h" #include @@ -63,17 +63,17 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ const uint32_t uv0 = (diag_12 + tl_uv) >> 1; \ const uint32_t uv1 = (diag_03 + t_uv) >> 1; \ FUNC(top_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ - top_dst + (2 * x - 1) * XSTEP); \ + top_dst + (2 * x - 1) * (XSTEP)); \ FUNC(top_y[2 * x - 0], uv1 & 0xff, (uv1 >> 16), \ - top_dst + (2 * x - 0) * XSTEP); \ + top_dst + (2 * x - 0) * (XSTEP)); \ } \ if (bottom_y != NULL) { \ const uint32_t uv0 = (diag_03 + l_uv) >> 1; \ const uint32_t uv1 = (diag_12 + uv) >> 1; \ FUNC(bottom_y[2 * x - 1], uv0 & 0xff, (uv0 >> 16), \ - bottom_dst + (2 * x - 1) * XSTEP); \ + bottom_dst + (2 * x - 1) * (XSTEP)); \ FUNC(bottom_y[2 * x + 0], uv1 & 0xff, (uv1 >> 16), \ - bottom_dst + (2 * x + 0) * XSTEP); \ + bottom_dst + (2 * x + 0) * (XSTEP)); \ } \ tl_uv = t_uv; \ l_uv = uv; \ @@ -82,24 +82,50 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ { \ const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ FUNC(top_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ - top_dst + (len - 1) * XSTEP); \ + top_dst + (len - 1) * (XSTEP)); \ } \ if (bottom_y != NULL) { \ const uint32_t uv0 = (3 * l_uv + tl_uv + 0x00020002u) >> 2; \ FUNC(bottom_y[len - 1], uv0 & 0xff, (uv0 >> 16), \ - bottom_dst + (len - 1) * XSTEP); \ + bottom_dst + (len - 1) * (XSTEP)); \ } \ } \ } // All variants implemented. -UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3) -UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3) -UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4) -UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4) -UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4) -UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2) -UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2) +#if !WEBP_NEON_OMIT_C_CODE +UPSAMPLE_FUNC(UpsampleRgbaLinePair_C, VP8YuvToRgba, 4) +UPSAMPLE_FUNC(UpsampleBgraLinePair_C, VP8YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +UPSAMPLE_FUNC(UpsampleArgbLinePair_C, VP8YuvToArgb, 4) +UPSAMPLE_FUNC(UpsampleRgbLinePair_C, VP8YuvToRgb, 3) +UPSAMPLE_FUNC(UpsampleBgrLinePair_C, VP8YuvToBgr, 3) +UPSAMPLE_FUNC(UpsampleRgba4444LinePair_C, VP8YuvToRgba4444, 2) +UPSAMPLE_FUNC(UpsampleRgb565LinePair_C, VP8YuvToRgb565, 2) +#else +static void EmptyUpsampleFunc(const uint8_t* top_y, const uint8_t* bottom_y, + const uint8_t* top_u, const uint8_t* top_v, + const uint8_t* cur_u, const uint8_t* cur_v, + uint8_t* top_dst, uint8_t* bottom_dst, int len) { + (void)top_y; + (void)bottom_y; + (void)top_u; + (void)top_v; + (void)cur_u; + (void)cur_v; + (void)top_dst; + (void)bottom_dst; + (void)len; + assert(0); // COLORSPACE SUPPORT NOT COMPILED +} +#define UpsampleArgbLinePair_C EmptyUpsampleFunc +#define UpsampleRgbLinePair_C EmptyUpsampleFunc +#define UpsampleBgrLinePair_C EmptyUpsampleFunc +#define UpsampleRgba4444LinePair_C EmptyUpsampleFunc +#define UpsampleRgb565LinePair_C EmptyUpsampleFunc +#endif // WEBP_REDUCE_CSP + +#endif #undef LOAD_UV #undef UPSAMPLE_FUNC @@ -141,7 +167,6 @@ DUAL_SAMPLE_FUNC(DualLineSamplerARGB, VP8YuvToArgb) WebPUpsampleLinePairFunc WebPGetLinePairConverter(int alpha_is_last) { WebPInitUpsamplers(); - VP8YUVInit(); #ifdef FANCY_UPSAMPLING return WebPUpsamplers[alpha_is_last ? MODE_BGRA : MODE_ARGB]; #else @@ -158,16 +183,33 @@ extern void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ uint8_t* dst, int len) { \ int i; \ - for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \ + for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * (XSTEP)]); \ } -YUV444_FUNC(WebPYuv444ToRgbC, VP8YuvToRgb, 3) -YUV444_FUNC(WebPYuv444ToBgrC, VP8YuvToBgr, 3) -YUV444_FUNC(WebPYuv444ToRgbaC, VP8YuvToRgba, 4) -YUV444_FUNC(WebPYuv444ToBgraC, VP8YuvToBgra, 4) -YUV444_FUNC(WebPYuv444ToArgbC, VP8YuvToArgb, 4) -YUV444_FUNC(WebPYuv444ToRgba4444C, VP8YuvToRgba4444, 2) -YUV444_FUNC(WebPYuv444ToRgb565C, VP8YuvToRgb565, 2) +YUV444_FUNC(WebPYuv444ToRgba_C, VP8YuvToRgba, 4) +YUV444_FUNC(WebPYuv444ToBgra_C, VP8YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +YUV444_FUNC(WebPYuv444ToRgb_C, VP8YuvToRgb, 3) +YUV444_FUNC(WebPYuv444ToBgr_C, VP8YuvToBgr, 3) +YUV444_FUNC(WebPYuv444ToArgb_C, VP8YuvToArgb, 4) +YUV444_FUNC(WebPYuv444ToRgba4444_C, VP8YuvToRgba4444, 2) +YUV444_FUNC(WebPYuv444ToRgb565_C, VP8YuvToRgb565, 2) +#else +static void EmptyYuv444Func(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { + (void)y; + (void)u; + (void)v; + (void)dst; + (void)len; +} +#define WebPYuv444ToRgb_C EmptyYuv444Func +#define WebPYuv444ToBgr_C EmptyYuv444Func +#define WebPYuv444ToArgb_C EmptyYuv444Func +#define WebPYuv444ToRgba4444_C EmptyYuv444Func +#define WebPYuv444ToRgb565_C EmptyYuv444Func +#endif // WEBP_REDUCE_CSP #undef YUV444_FUNC @@ -182,17 +224,17 @@ static volatile VP8CPUInfo upsampling_last_cpuinfo_used1 = WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444Converters(void) { if (upsampling_last_cpuinfo_used1 == VP8GetCPUInfo) return; - WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgbC; - WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgbaC; - WebPYUV444Converters[MODE_BGR] = WebPYuv444ToBgrC; - WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgraC; - WebPYUV444Converters[MODE_ARGB] = WebPYuv444ToArgbC; - WebPYUV444Converters[MODE_RGBA_4444] = WebPYuv444ToRgba4444C; - WebPYUV444Converters[MODE_RGB_565] = WebPYuv444ToRgb565C; - WebPYUV444Converters[MODE_rgbA] = WebPYuv444ToRgbaC; - WebPYUV444Converters[MODE_bgrA] = WebPYuv444ToBgraC; - WebPYUV444Converters[MODE_Argb] = WebPYuv444ToArgbC; - WebPYUV444Converters[MODE_rgbA_4444] = WebPYuv444ToRgba4444C; + WebPYUV444Converters[MODE_RGBA] = WebPYuv444ToRgba_C; + WebPYUV444Converters[MODE_BGRA] = WebPYuv444ToBgra_C; + WebPYUV444Converters[MODE_RGB] = WebPYuv444ToRgb_C; + WebPYUV444Converters[MODE_BGR] = WebPYuv444ToBgr_C; + WebPYUV444Converters[MODE_ARGB] = WebPYuv444ToArgb_C; + WebPYUV444Converters[MODE_RGBA_4444] = WebPYuv444ToRgba4444_C; + WebPYUV444Converters[MODE_RGB_565] = WebPYuv444ToRgb565_C; + WebPYUV444Converters[MODE_rgbA] = WebPYuv444ToRgba_C; + WebPYUV444Converters[MODE_bgrA] = WebPYuv444ToBgra_C; + WebPYUV444Converters[MODE_Argb] = WebPYuv444ToArgb_C; + WebPYUV444Converters[MODE_rgbA_4444] = WebPYuv444ToRgba4444_C; if (VP8GetCPUInfo != NULL) { #if defined(WEBP_USE_SSE2) @@ -224,17 +266,19 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) { if (upsampling_last_cpuinfo_used2 == VP8GetCPUInfo) return; #ifdef FANCY_UPSAMPLING - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; - WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; - WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; - WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; +#if !WEBP_NEON_OMIT_C_CODE + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_C; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair_C; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair_C; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair_C; + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_C; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_C; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair_C; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair_C; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair_C; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair_C; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair_C; +#endif // If defined, use CPUInfo() to overwrite some pointers with faster versions. if (VP8GetCPUInfo != NULL) { @@ -243,11 +287,6 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) { WebPInitUpsamplersSSE2(); } #endif -#if defined(WEBP_USE_NEON) - if (VP8GetCPUInfo(kNEON)) { - WebPInitUpsamplersNEON(); - } -#endif #if defined(WEBP_USE_MIPS_DSP_R2) if (VP8GetCPUInfo(kMIPSdspR2)) { WebPInitUpsamplersMIPSdspR2(); @@ -259,6 +298,26 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplers(void) { } #endif } + +#if defined(WEBP_USE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPInitUpsamplersNEON(); + } +#endif + + assert(WebPUpsamplers[MODE_RGBA] != NULL); + assert(WebPUpsamplers[MODE_BGRA] != NULL); + assert(WebPUpsamplers[MODE_rgbA] != NULL); + assert(WebPUpsamplers[MODE_bgrA] != NULL); + assert(WebPUpsamplers[MODE_RGB] != NULL); + assert(WebPUpsamplers[MODE_BGR] != NULL); + assert(WebPUpsamplers[MODE_ARGB] != NULL); + assert(WebPUpsamplers[MODE_RGBA_4444] != NULL); + assert(WebPUpsamplers[MODE_RGB_565] != NULL); + assert(WebPUpsamplers[MODE_Argb] != NULL); + assert(WebPUpsamplers[MODE_rgbA_4444] != NULL); + #endif // FANCY_UPSAMPLING upsampling_last_cpuinfo_used2 = VP8GetCPUInfo; } diff --git a/3rdparty/libwebp/dsp/upsampling_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/upsampling_mips_dsp_r2.c similarity index 96% rename from 3rdparty/libwebp/dsp/upsampling_mips_dsp_r2.c rename to 3rdparty/libwebp/src/dsp/upsampling_mips_dsp_r2.c index ed2eb74825..10d499d771 100644 --- a/3rdparty/libwebp/dsp/upsampling_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/upsampling_mips_dsp_r2.c @@ -12,14 +12,12 @@ // Author(s): Branimir Vasic (branimir.vasic@imgtec.com) // Djordje Pesut (djordje.pesut@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS_DSP_R2) #include -#include "./yuv.h" - -#if !defined(WEBP_YUV_USE_TABLE) +#include "src/dsp/yuv.h" #define YUV_TO_RGB(Y, U, V, R, G, B) do { \ const int t1 = MultHi(Y, 19077); \ @@ -48,6 +46,7 @@ ); \ } while (0) +#if !defined(WEBP_REDUCE_CSP) static WEBP_INLINE void YuvToRgb(int y, int u, int v, uint8_t* const rgb) { int r, g, b; YUV_TO_RGB(y, u, v, r, g, b); @@ -68,7 +67,7 @@ static WEBP_INLINE void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) { { const int rg = (r & 0xf8) | (g >> 5); const int gb = ((g << 3) & 0xe0) | (b >> 3); -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) rgb[0] = gb; rgb[1] = rg; #else @@ -84,7 +83,7 @@ static WEBP_INLINE void YuvToRgba4444(int y, int u, int v, { const int rg = (r & 0xf0) | (g >> 4); const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) argb[0] = ba; argb[1] = rg; #else @@ -93,11 +92,12 @@ static WEBP_INLINE void YuvToRgba4444(int y, int u, int v, #endif } } -#endif // WEBP_YUV_USE_TABLE +#endif // WEBP_REDUCE_CSP //----------------------------------------------------------------------------- // Alpha handling variants +#if !defined(WEBP_REDUCE_CSP) static WEBP_INLINE void YuvToArgb(uint8_t y, uint8_t u, uint8_t v, uint8_t* const argb) { int r, g, b; @@ -107,6 +107,7 @@ static WEBP_INLINE void YuvToArgb(uint8_t y, uint8_t u, uint8_t v, argb[2] = g; argb[3] = b; } +#endif // WEBP_REDUCE_CSP static WEBP_INLINE void YuvToBgra(uint8_t y, uint8_t u, uint8_t v, uint8_t* const bgra) { int r, g, b; @@ -200,13 +201,15 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ } // All variants implemented. -UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3) -UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3) UPSAMPLE_FUNC(UpsampleRgbaLinePair, YuvToRgba, 4) UPSAMPLE_FUNC(UpsampleBgraLinePair, YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3) +UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3) UPSAMPLE_FUNC(UpsampleArgbLinePair, YuvToArgb, 4) UPSAMPLE_FUNC(UpsampleRgba4444LinePair, YuvToRgba4444, 2) UPSAMPLE_FUNC(UpsampleRgb565LinePair, YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP #undef LOAD_UV #undef UPSAMPLE_FUNC @@ -217,17 +220,19 @@ UPSAMPLE_FUNC(UpsampleRgb565LinePair, YuvToRgb565, 2) extern void WebPInitUpsamplersMIPSdspR2(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersMIPSdspR2(void) { - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; +#endif // WEBP_REDUCE_CSP } #endif // FANCY_UPSAMPLING @@ -242,13 +247,15 @@ static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ for (i = 0; i < len; ++i) FUNC(y[i], u[i], v[i], &dst[i * XSTEP]); \ } -YUV444_FUNC(Yuv444ToRgb, YuvToRgb, 3) -YUV444_FUNC(Yuv444ToBgr, YuvToBgr, 3) YUV444_FUNC(Yuv444ToRgba, YuvToRgba, 4) YUV444_FUNC(Yuv444ToBgra, YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +YUV444_FUNC(Yuv444ToRgb, YuvToRgb, 3) +YUV444_FUNC(Yuv444ToBgr, YuvToBgr, 3) YUV444_FUNC(Yuv444ToArgb, YuvToArgb, 4) YUV444_FUNC(Yuv444ToRgba4444, YuvToRgba4444, 2) YUV444_FUNC(Yuv444ToRgb565, YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP #undef YUV444_FUNC @@ -258,17 +265,19 @@ YUV444_FUNC(Yuv444ToRgb565, YuvToRgb565, 2) extern void WebPInitYUV444ConvertersMIPSdspR2(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersMIPSdspR2(void) { - WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb; WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba; - WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr; WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra; + WebPYUV444Converters[MODE_rgbA] = Yuv444ToRgba; + WebPYUV444Converters[MODE_bgrA] = Yuv444ToBgra; +#if !defined(WEBP_REDUCE_CSP) + WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb; + WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr; WebPYUV444Converters[MODE_ARGB] = Yuv444ToArgb; WebPYUV444Converters[MODE_RGBA_4444] = Yuv444ToRgba4444; WebPYUV444Converters[MODE_RGB_565] = Yuv444ToRgb565; - WebPYUV444Converters[MODE_rgbA] = Yuv444ToRgba; - WebPYUV444Converters[MODE_bgrA] = Yuv444ToBgra; WebPYUV444Converters[MODE_Argb] = Yuv444ToArgb; WebPYUV444Converters[MODE_rgbA_4444] = Yuv444ToRgba4444; +#endif // WEBP_REDUCE_CSP } #else // !WEBP_USE_MIPS_DSP_R2 diff --git a/3rdparty/libwebp/dsp/upsampling_msa.c b/3rdparty/libwebp/src/dsp/upsampling_msa.c similarity index 97% rename from 3rdparty/libwebp/dsp/upsampling_msa.c rename to 3rdparty/libwebp/src/dsp/upsampling_msa.c index f24926fa94..535ffb772c 100644 --- a/3rdparty/libwebp/dsp/upsampling_msa.c +++ b/3rdparty/libwebp/src/dsp/upsampling_msa.c @@ -12,12 +12,12 @@ // Author: Prashant Patil (prashant.patil@imgtec.com) #include -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MSA) -#include "./msa_macro.h" -#include "./yuv.h" +#include "src/dsp/msa_macro.h" +#include "src/dsp/yuv.h" #ifdef FANCY_UPSAMPLING @@ -274,7 +274,7 @@ static void YuvToRgb565(int y, int u, int v, uint8_t* const rgb) { const int b = Clip8(b1 >> 6); const int rg = (r & 0xf8) | (g >> 5); const int gb = ((g << 3) & 0xe0) | (b >> 3); -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) rgb[0] = gb; rgb[1] = rg; #else @@ -293,7 +293,7 @@ static void YuvToRgba4444(int y, int u, int v, uint8_t* const argb) { const int b = Clip8(b1 >> 6); const int rg = (r & 0xf0) | (g >> 4); const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) argb[0] = ba; argb[1] = rg; #else @@ -374,7 +374,7 @@ static void YuvToBgrLine(const uint8_t* y, const uint8_t* u, static void YuvToRgbaLine(const uint8_t* y, const uint8_t* u, const uint8_t* v, uint8_t* dst, int length) { v16u8 R, G, B; - const v16u8 A = (v16u8)__msa_ldi_b(0xff); + const v16u8 A = (v16u8)__msa_ldi_b(ALPHAVAL); while (length >= 16) { CALC_RGB16(y, u, v, R, G, B); STORE16_4(R, G, B, A, dst); @@ -402,7 +402,7 @@ static void YuvToRgbaLine(const uint8_t* y, const uint8_t* u, static void YuvToBgraLine(const uint8_t* y, const uint8_t* u, const uint8_t* v, uint8_t* dst, int length) { v16u8 R, G, B; - const v16u8 A = (v16u8)__msa_ldi_b(0xff); + const v16u8 A = (v16u8)__msa_ldi_b(ALPHAVAL); while (length >= 16) { CALC_RGB16(y, u, v, R, G, B); STORE16_4(B, G, R, A, dst); @@ -430,7 +430,7 @@ static void YuvToBgraLine(const uint8_t* y, const uint8_t* u, static void YuvToArgbLine(const uint8_t* y, const uint8_t* u, const uint8_t* v, uint8_t* dst, int length) { v16u8 R, G, B; - const v16u8 A = (v16u8)__msa_ldi_b(0xff); + const v16u8 A = (v16u8)__msa_ldi_b(ALPHAVAL); while (length >= 16) { CALC_RGB16(y, u, v, R, G, B); STORE16_4(A, R, G, B, dst); @@ -459,11 +459,11 @@ static void YuvToRgba4444Line(const uint8_t* y, const uint8_t* u, const uint8_t* v, uint8_t* dst, int length) { v16u8 R, G, B, RG, BA, tmp0, tmp1; while (length >= 16) { - #ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) CALC_RGBA4444(y, u, v, BA, RG, 16, dst); - #else +#else CALC_RGBA4444(y, u, v, RG, BA, 16, dst); - #endif +#endif y += 16; u += 16; v += 16; @@ -473,7 +473,7 @@ static void YuvToRgba4444Line(const uint8_t* y, const uint8_t* u, if (length > 8) { uint8_t temp[2 * 16] = { 0 }; memcpy(temp, y, length * sizeof(*temp)); -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) CALC_RGBA4444(temp, u, v, BA, RG, 16, temp); #else CALC_RGBA4444(temp, u, v, RG, BA, 16, temp); @@ -482,7 +482,7 @@ static void YuvToRgba4444Line(const uint8_t* y, const uint8_t* u, } else if (length > 0) { uint8_t temp[2 * 8] = { 0 }; memcpy(temp, y, length * sizeof(*temp)); -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) CALC_RGBA4444(temp, u, v, BA, RG, 8, temp); #else CALC_RGBA4444(temp, u, v, RG, BA, 8, temp); @@ -495,11 +495,11 @@ static void YuvToRgb565Line(const uint8_t* y, const uint8_t* u, const uint8_t* v, uint8_t* dst, int length) { v16u8 R, G, B, RG, GB, tmp0, tmp1; while (length >= 16) { - #ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) CALC_RGB565(y, u, v, GB, RG, 16, dst); - #else +#else CALC_RGB565(y, u, v, RG, GB, 16, dst); - #endif +#endif y += 16; u += 16; v += 16; @@ -509,7 +509,7 @@ static void YuvToRgb565Line(const uint8_t* y, const uint8_t* u, if (length > 8) { uint8_t temp[2 * 16] = { 0 }; memcpy(temp, y, length * sizeof(*temp)); -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) CALC_RGB565(temp, u, v, GB, RG, 16, temp); #else CALC_RGB565(temp, u, v, RG, GB, 16, temp); @@ -518,7 +518,7 @@ static void YuvToRgb565Line(const uint8_t* y, const uint8_t* u, } else if (length > 0) { uint8_t temp[2 * 8] = { 0 }; memcpy(temp, y, length * sizeof(*temp)); -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) CALC_RGB565(temp, u, v, GB, RG, 8, temp); #else CALC_RGB565(temp, u, v, RG, GB, 8, temp); @@ -640,13 +640,15 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \ } \ } -UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3) -UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3) UPSAMPLE_FUNC(UpsampleRgbaLinePair, YuvToRgba, 4) UPSAMPLE_FUNC(UpsampleBgraLinePair, YuvToBgra, 4) +#if !defined(WEBP_REDUCE_CSP) +UPSAMPLE_FUNC(UpsampleRgbLinePair, YuvToRgb, 3) +UPSAMPLE_FUNC(UpsampleBgrLinePair, YuvToBgr, 3) UPSAMPLE_FUNC(UpsampleArgbLinePair, YuvToArgb, 4) UPSAMPLE_FUNC(UpsampleRgba4444LinePair, YuvToRgba4444, 2) UPSAMPLE_FUNC(UpsampleRgb565LinePair, YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP //------------------------------------------------------------------------------ // Entry point @@ -656,17 +658,19 @@ extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; extern void WebPInitUpsamplersMSA(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersMSA(void) { - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; +#endif // WEBP_REDUCE_CSP } #endif // FANCY_UPSAMPLING diff --git a/3rdparty/libwebp/dsp/upsampling_neon.c b/3rdparty/libwebp/src/dsp/upsampling_neon.c similarity index 90% rename from 3rdparty/libwebp/dsp/upsampling_neon.c rename to 3rdparty/libwebp/src/dsp/upsampling_neon.c index d371a834ff..17cbc9f911 100644 --- a/3rdparty/libwebp/dsp/upsampling_neon.c +++ b/3rdparty/libwebp/src/dsp/upsampling_neon.c @@ -12,15 +12,15 @@ // Author: mans@mansr.com (Mans Rullgard) // Based on SSE code by: somnath@google.com (Somnath Banerjee) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_NEON) #include #include #include -#include "./neon.h" -#include "./yuv.h" +#include "src/dsp/neon.h" +#include "src/dsp/yuv.h" #ifdef FANCY_UPSAMPLING @@ -58,8 +58,8 @@ } while (0) // Turn the macro into a function for reducing code-size when non-critical -static void Upsample16Pixels(const uint8_t *r1, const uint8_t *r2, - uint8_t *out) { +static void Upsample16Pixels_NEON(const uint8_t *r1, const uint8_t *r2, + uint8_t *out) { UPSAMPLE_16PIXELS(r1, r2, out); } @@ -70,7 +70,7 @@ static void Upsample16Pixels(const uint8_t *r1, const uint8_t *r2, /* replicate last byte */ \ memset(r1 + (num_pixels), r1[(num_pixels) - 1], 9 - (num_pixels)); \ memset(r2 + (num_pixels), r2[(num_pixels) - 1], 9 - (num_pixels)); \ - Upsample16Pixels(r1, r2, out); \ + Upsample16Pixels_NEON(r1, r2, out); \ } //----------------------------------------------------------------------------- @@ -243,13 +243,15 @@ static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \ } // NEON variants of the fancy upsampler. -NEON_UPSAMPLE_FUNC(UpsampleRgbLinePair, Rgb, 3) -NEON_UPSAMPLE_FUNC(UpsampleBgrLinePair, Bgr, 3) -NEON_UPSAMPLE_FUNC(UpsampleRgbaLinePair, Rgba, 4) -NEON_UPSAMPLE_FUNC(UpsampleBgraLinePair, Bgra, 4) -NEON_UPSAMPLE_FUNC(UpsampleArgbLinePair, Argb, 4) -NEON_UPSAMPLE_FUNC(UpsampleRgba4444LinePair, Rgba4444, 2) -NEON_UPSAMPLE_FUNC(UpsampleRgb565LinePair, Rgb565, 2) +NEON_UPSAMPLE_FUNC(UpsampleRgbaLinePair_NEON, Rgba, 4) +NEON_UPSAMPLE_FUNC(UpsampleBgraLinePair_NEON, Bgra, 4) +#if !defined(WEBP_REDUCE_CSP) +NEON_UPSAMPLE_FUNC(UpsampleRgbLinePair_NEON, Rgb, 3) +NEON_UPSAMPLE_FUNC(UpsampleBgrLinePair_NEON, Bgr, 3) +NEON_UPSAMPLE_FUNC(UpsampleArgbLinePair_NEON, Argb, 4) +NEON_UPSAMPLE_FUNC(UpsampleRgba4444LinePair_NEON, Rgba4444, 2) +NEON_UPSAMPLE_FUNC(UpsampleRgb565LinePair_NEON, Rgb565, 2) +#endif // WEBP_REDUCE_CSP //------------------------------------------------------------------------------ // Entry point @@ -259,17 +261,19 @@ extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; extern void WebPInitUpsamplersNEON(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersNEON(void) { - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; - WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; - WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_NEON; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair_NEON; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair_NEON; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair_NEON; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_NEON; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_NEON; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair_NEON; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair_NEON; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair_NEON; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair_NEON; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair_NEON; +#endif // WEBP_REDUCE_CSP } #endif // FANCY_UPSAMPLING diff --git a/3rdparty/libwebp/dsp/upsampling_sse2.c b/3rdparty/libwebp/src/dsp/upsampling_sse2.c similarity index 72% rename from 3rdparty/libwebp/dsp/upsampling_sse2.c rename to 3rdparty/libwebp/src/dsp/upsampling_sse2.c index b5b668900f..fd5d303982 100644 --- a/3rdparty/libwebp/dsp/upsampling_sse2.c +++ b/3rdparty/libwebp/src/dsp/upsampling_sse2.c @@ -11,14 +11,14 @@ // // Author: somnath@google.com (Somnath Banerjee) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_SSE2) #include #include #include -#include "./yuv.h" +#include "src/dsp/yuv.h" #ifdef FANCY_UPSAMPLING @@ -83,13 +83,13 @@ GET_M(ad, s, diag2); /* diag2 = (3a + b + c + 3d) / 8 */ \ \ /* pack the alternate pixels */ \ - PACK_AND_STORE(a, b, diag1, diag2, out + 0); /* store top */ \ - PACK_AND_STORE(c, d, diag2, diag1, out + 2 * 32); /* store bottom */ \ + PACK_AND_STORE(a, b, diag1, diag2, (out) + 0); /* store top */ \ + PACK_AND_STORE(c, d, diag2, diag1, (out) + 2 * 32); /* store bottom */ \ } // Turn the macro into a function for reducing code-size when non-critical -static void Upsample32Pixels(const uint8_t r1[], const uint8_t r2[], - uint8_t* const out) { +static void Upsample32Pixels_SSE2(const uint8_t r1[], const uint8_t r2[], + uint8_t* const out) { UPSAMPLE_32PIXELS(r1, r2, out); } @@ -101,30 +101,30 @@ static void Upsample32Pixels(const uint8_t r1[], const uint8_t r2[], memset(r1 + (num_pixels), r1[(num_pixels) - 1], 17 - (num_pixels)); \ memset(r2 + (num_pixels), r2[(num_pixels) - 1], 17 - (num_pixels)); \ /* using the shared function instead of the macro saves ~3k code size */ \ - Upsample32Pixels(r1, r2, out); \ + Upsample32Pixels_SSE2(r1, r2, out); \ } #define CONVERT2RGB(FUNC, XSTEP, top_y, bottom_y, \ top_dst, bottom_dst, cur_x, num_pixels) { \ int n; \ for (n = 0; n < (num_pixels); ++n) { \ - FUNC(top_y[(cur_x) + n], r_u[n], r_v[n], \ - top_dst + ((cur_x) + n) * XSTEP); \ + FUNC((top_y)[(cur_x) + n], r_u[n], r_v[n], \ + (top_dst) + ((cur_x) + n) * (XSTEP)); \ } \ - if (bottom_y != NULL) { \ + if ((bottom_y) != NULL) { \ for (n = 0; n < (num_pixels); ++n) { \ - FUNC(bottom_y[(cur_x) + n], r_u[64 + n], r_v[64 + n], \ - bottom_dst + ((cur_x) + n) * XSTEP); \ + FUNC((bottom_y)[(cur_x) + n], r_u[64 + n], r_v[64 + n], \ + (bottom_dst) + ((cur_x) + n) * (XSTEP)); \ } \ } \ } #define CONVERT2RGB_32(FUNC, XSTEP, top_y, bottom_y, \ top_dst, bottom_dst, cur_x) do { \ - FUNC##32(top_y + (cur_x), r_u, r_v, top_dst + (cur_x) * XSTEP); \ - if (bottom_y != NULL) { \ - FUNC##32(bottom_y + (cur_x), r_u + 64, r_v + 64, \ - bottom_dst + (cur_x) * XSTEP); \ + FUNC##32_SSE2((top_y) + (cur_x), r_u, r_v, (top_dst) + (cur_x) * (XSTEP)); \ + if ((bottom_y) != NULL) { \ + FUNC##32_SSE2((bottom_y) + (cur_x), r_u + 64, r_v + 64, \ + (bottom_dst) + (cur_x) * (XSTEP)); \ } \ } while (0) @@ -169,13 +169,16 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \ } // SSE2 variants of the fancy upsampler. -SSE2_UPSAMPLE_FUNC(UpsampleRgbLinePair, VP8YuvToRgb, 3) -SSE2_UPSAMPLE_FUNC(UpsampleBgrLinePair, VP8YuvToBgr, 3) -SSE2_UPSAMPLE_FUNC(UpsampleRgbaLinePair, VP8YuvToRgba, 4) -SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePair, VP8YuvToBgra, 4) -SSE2_UPSAMPLE_FUNC(UpsampleArgbLinePair, VP8YuvToArgb, 4) -SSE2_UPSAMPLE_FUNC(UpsampleRgba4444LinePair, VP8YuvToRgba4444, 2) -SSE2_UPSAMPLE_FUNC(UpsampleRgb565LinePair, VP8YuvToRgb565, 2) +SSE2_UPSAMPLE_FUNC(UpsampleRgbaLinePair_SSE2, VP8YuvToRgba, 4) +SSE2_UPSAMPLE_FUNC(UpsampleBgraLinePair_SSE2, VP8YuvToBgra, 4) + +#if !defined(WEBP_REDUCE_CSP) +SSE2_UPSAMPLE_FUNC(UpsampleRgbLinePair_SSE2, VP8YuvToRgb, 3) +SSE2_UPSAMPLE_FUNC(UpsampleBgrLinePair_SSE2, VP8YuvToBgr, 3) +SSE2_UPSAMPLE_FUNC(UpsampleArgbLinePair_SSE2, VP8YuvToArgb, 4) +SSE2_UPSAMPLE_FUNC(UpsampleRgba4444LinePair_SSE2, VP8YuvToRgba4444, 2) +SSE2_UPSAMPLE_FUNC(UpsampleRgb565LinePair_SSE2, VP8YuvToRgb565, 2) +#endif // WEBP_REDUCE_CSP #undef GET_M #undef PACK_AND_STORE @@ -193,17 +196,19 @@ extern WebPUpsampleLinePairFunc WebPUpsamplers[/* MODE_LAST */]; extern void WebPInitUpsamplersSSE2(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE2(void) { - WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair; - WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair; - WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair; - WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair; - WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair; - WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair; - WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair; - WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair; + WebPUpsamplers[MODE_RGBA] = UpsampleRgbaLinePair_SSE2; + WebPUpsamplers[MODE_BGRA] = UpsampleBgraLinePair_SSE2; + WebPUpsamplers[MODE_rgbA] = UpsampleRgbaLinePair_SSE2; + WebPUpsamplers[MODE_bgrA] = UpsampleBgraLinePair_SSE2; +#if !defined(WEBP_REDUCE_CSP) + WebPUpsamplers[MODE_RGB] = UpsampleRgbLinePair_SSE2; + WebPUpsamplers[MODE_BGR] = UpsampleBgrLinePair_SSE2; + WebPUpsamplers[MODE_ARGB] = UpsampleArgbLinePair_SSE2; + WebPUpsamplers[MODE_Argb] = UpsampleArgbLinePair_SSE2; + WebPUpsamplers[MODE_RGB_565] = UpsampleRgb565LinePair_SSE2; + WebPUpsamplers[MODE_RGBA_4444] = UpsampleRgba4444LinePair_SSE2; + WebPUpsamplers[MODE_rgbA_4444] = UpsampleRgba4444LinePair_SSE2; +#endif // WEBP_REDUCE_CSP } #endif // FANCY_UPSAMPLING @@ -213,29 +218,46 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitUpsamplersSSE2(void) { extern WebPYUV444Converter WebPYUV444Converters[/* MODE_LAST */]; extern void WebPInitYUV444ConvertersSSE2(void); -#define YUV444_FUNC(FUNC_NAME, CALL, XSTEP) \ -extern void WebP##FUNC_NAME##C(const uint8_t* y, const uint8_t* u, \ - const uint8_t* v, uint8_t* dst, int len); \ +#define YUV444_FUNC(FUNC_NAME, CALL, CALL_C, XSTEP) \ +extern void CALL_C(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ + uint8_t* dst, int len); \ static void FUNC_NAME(const uint8_t* y, const uint8_t* u, const uint8_t* v, \ uint8_t* dst, int len) { \ int i; \ const int max_len = len & ~31; \ - for (i = 0; i < max_len; i += 32) CALL(y + i, u + i, v + i, dst + i * XSTEP);\ + for (i = 0; i < max_len; i += 32) { \ + CALL(y + i, u + i, v + i, dst + i * (XSTEP)); \ + } \ if (i < len) { /* C-fallback */ \ - WebP##FUNC_NAME##C(y + i, u + i, v + i, dst + i * XSTEP, len - i); \ + CALL_C(y + i, u + i, v + i, dst + i * (XSTEP), len - i); \ } \ } -YUV444_FUNC(Yuv444ToRgba, VP8YuvToRgba32, 4); -YUV444_FUNC(Yuv444ToBgra, VP8YuvToBgra32, 4); -YUV444_FUNC(Yuv444ToRgb, VP8YuvToRgb32, 3); -YUV444_FUNC(Yuv444ToBgr, VP8YuvToBgr32, 3); +YUV444_FUNC(Yuv444ToRgba_SSE2, VP8YuvToRgba32_SSE2, WebPYuv444ToRgba_C, 4); +YUV444_FUNC(Yuv444ToBgra_SSE2, VP8YuvToBgra32_SSE2, WebPYuv444ToBgra_C, 4); +#if !defined(WEBP_REDUCE_CSP) +YUV444_FUNC(Yuv444ToRgb_SSE2, VP8YuvToRgb32_SSE2, WebPYuv444ToRgb_C, 3); +YUV444_FUNC(Yuv444ToBgr_SSE2, VP8YuvToBgr32_SSE2, WebPYuv444ToBgr_C, 3); +YUV444_FUNC(Yuv444ToArgb_SSE2, VP8YuvToArgb32_SSE2, WebPYuv444ToArgb_C, 4) +YUV444_FUNC(Yuv444ToRgba4444_SSE2, VP8YuvToRgba444432_SSE2, \ + WebPYuv444ToRgba4444_C, 2) +YUV444_FUNC(Yuv444ToRgb565_SSE2, VP8YuvToRgb56532_SSE2, WebPYuv444ToRgb565_C, 2) +#endif // WEBP_REDUCE_CSP WEBP_TSAN_IGNORE_FUNCTION void WebPInitYUV444ConvertersSSE2(void) { - WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba; - WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra; - WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb; - WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr; + WebPYUV444Converters[MODE_RGBA] = Yuv444ToRgba_SSE2; + WebPYUV444Converters[MODE_BGRA] = Yuv444ToBgra_SSE2; + WebPYUV444Converters[MODE_rgbA] = Yuv444ToRgba_SSE2; + WebPYUV444Converters[MODE_bgrA] = Yuv444ToBgra_SSE2; +#if !defined(WEBP_REDUCE_CSP) + WebPYUV444Converters[MODE_RGB] = Yuv444ToRgb_SSE2; + WebPYUV444Converters[MODE_BGR] = Yuv444ToBgr_SSE2; + WebPYUV444Converters[MODE_ARGB] = Yuv444ToArgb_SSE2; + WebPYUV444Converters[MODE_RGBA_4444] = Yuv444ToRgba4444_SSE2; + WebPYUV444Converters[MODE_RGB_565] = Yuv444ToRgb565_SSE2; + WebPYUV444Converters[MODE_Argb] = Yuv444ToArgb_SSE2; + WebPYUV444Converters[MODE_rgbA_4444] = Yuv444ToRgba4444_SSE2; +#endif // WEBP_REDUCE_CSP } #else diff --git a/3rdparty/libwebp/dsp/yuv.c b/3rdparty/libwebp/src/dsp/yuv.c similarity index 82% rename from 3rdparty/libwebp/dsp/yuv.c rename to 3rdparty/libwebp/src/dsp/yuv.c index dd7d9dedfa..bddf81fe09 100644 --- a/3rdparty/libwebp/dsp/yuv.c +++ b/3rdparty/libwebp/src/dsp/yuv.c @@ -11,63 +11,11 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./yuv.h" +#include "src/dsp/yuv.h" +#include #include -#if defined(WEBP_YUV_USE_TABLE) - -static int done = 0; - -static WEBP_INLINE uint8_t clip(int v, int max_value) { - return v < 0 ? 0 : v > max_value ? max_value : v; -} - -int16_t VP8kVToR[256], VP8kUToB[256]; -int32_t VP8kVToG[256], VP8kUToG[256]; -uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; -uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN]; - -WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) { - int i; - if (done) { - return; - } -#ifndef USE_YUVj - for (i = 0; i < 256; ++i) { - VP8kVToR[i] = (89858 * (i - 128) + YUV_HALF) >> YUV_FIX; - VP8kUToG[i] = -22014 * (i - 128) + YUV_HALF; - VP8kVToG[i] = -45773 * (i - 128); - VP8kUToB[i] = (113618 * (i - 128) + YUV_HALF) >> YUV_FIX; - } - for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) { - const int k = ((i - 16) * 76283 + YUV_HALF) >> YUV_FIX; - VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); - VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); - } -#else - for (i = 0; i < 256; ++i) { - VP8kVToR[i] = (91881 * (i - 128) + YUV_HALF) >> YUV_FIX; - VP8kUToG[i] = -22554 * (i - 128) + YUV_HALF; - VP8kVToG[i] = -46802 * (i - 128); - VP8kUToB[i] = (116130 * (i - 128) + YUV_HALF) >> YUV_FIX; - } - for (i = YUV_RANGE_MIN; i < YUV_RANGE_MAX; ++i) { - const int k = i; - VP8kClip[i - YUV_RANGE_MIN] = clip(k, 255); - VP8kClip4Bits[i - YUV_RANGE_MIN] = clip((k + 8) >> 4, 15); - } -#endif - - done = 1; -} - -#else - -WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) {} - -#endif // WEBP_YUV_USE_TABLE - //----------------------------------------------------------------------------- // Plain-C version @@ -75,14 +23,14 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8YUVInit(void) {} static void FUNC_NAME(const uint8_t* y, \ const uint8_t* u, const uint8_t* v, \ uint8_t* dst, int len) { \ - const uint8_t* const end = dst + (len & ~1) * XSTEP; \ + const uint8_t* const end = dst + (len & ~1) * (XSTEP); \ while (dst != end) { \ FUNC(y[0], u[0], v[0], dst); \ - FUNC(y[1], u[0], v[0], dst + XSTEP); \ + FUNC(y[1], u[0], v[0], dst + (XSTEP)); \ y += 2; \ ++u; \ ++v; \ - dst += 2 * XSTEP; \ + dst += 2 * (XSTEP); \ } \ if (len & 1) { \ FUNC(y[0], u[0], v[0], dst); \ @@ -168,7 +116,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplers(void) { //----------------------------------------------------------------------------- // ARGB -> YUV converters -static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) { +static void ConvertARGBToY_C(const uint32_t* argb, uint8_t* y, int width) { int i; for (i = 0; i < width; ++i) { const uint32_t p = argb[i]; @@ -220,14 +168,14 @@ void WebPConvertARGBToUV_C(const uint32_t* argb, uint8_t* u, uint8_t* v, //----------------------------------------------------------------------------- -static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) { +static void ConvertRGB24ToY_C(const uint8_t* rgb, uint8_t* y, int width) { int i; for (i = 0; i < width; ++i, rgb += 3) { y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); } } -static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) { +static void ConvertBGR24ToY_C(const uint8_t* bgr, uint8_t* y, int width) { int i; for (i = 0; i < width; ++i, bgr += 3) { y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); @@ -246,6 +194,7 @@ void WebPConvertRGBA32ToUV_C(const uint16_t* rgb, //----------------------------------------------------------------------------- +#if !WEBP_NEON_OMIT_C_CODE #define MAX_Y ((1 << 10) - 1) // 10b precision over 16b-arithmetic static uint16_t clip_y(int v) { return (v < 0) ? 0 : (v > MAX_Y) ? MAX_Y : (uint16_t)v; @@ -283,6 +232,7 @@ static void SharpYUVFilterRow_C(const int16_t* A, const int16_t* B, int len, out[2 * i + 1] = clip_y(best_y[2 * i + 1] + v1); } } +#endif // !WEBP_NEON_OMIT_C_CODE #undef MAX_Y @@ -308,22 +258,26 @@ static volatile VP8CPUInfo rgba_to_yuv_last_cpuinfo_used = (VP8CPUInfo)&rgba_to_yuv_last_cpuinfo_used; extern void WebPInitConvertARGBToYUVSSE2(void); +extern void WebPInitConvertARGBToYUVNEON(void); extern void WebPInitSharpYUVSSE2(void); +extern void WebPInitSharpYUVNEON(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) { if (rgba_to_yuv_last_cpuinfo_used == VP8GetCPUInfo) return; - WebPConvertARGBToY = ConvertARGBToY; + WebPConvertARGBToY = ConvertARGBToY_C; WebPConvertARGBToUV = WebPConvertARGBToUV_C; - WebPConvertRGB24ToY = ConvertRGB24ToY; - WebPConvertBGR24ToY = ConvertBGR24ToY; + WebPConvertRGB24ToY = ConvertRGB24ToY_C; + WebPConvertBGR24ToY = ConvertBGR24ToY_C; WebPConvertRGBA32ToUV = WebPConvertRGBA32ToUV_C; +#if !WEBP_NEON_OMIT_C_CODE WebPSharpYUVUpdateY = SharpYUVUpdateY_C; WebPSharpYUVUpdateRGB = SharpYUVUpdateRGB_C; WebPSharpYUVFilterRow = SharpYUVFilterRow_C; +#endif if (VP8GetCPUInfo != NULL) { #if defined(WEBP_USE_SSE2) @@ -333,5 +287,23 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUV(void) { } #endif // WEBP_USE_SSE2 } + +#if defined(WEBP_USE_NEON) + if (WEBP_NEON_OMIT_C_CODE || + (VP8GetCPUInfo != NULL && VP8GetCPUInfo(kNEON))) { + WebPInitConvertARGBToYUVNEON(); + WebPInitSharpYUVNEON(); + } +#endif // WEBP_USE_NEON + + assert(WebPConvertARGBToY != NULL); + assert(WebPConvertARGBToUV != NULL); + assert(WebPConvertRGB24ToY != NULL); + assert(WebPConvertBGR24ToY != NULL); + assert(WebPConvertRGBA32ToUV != NULL); + assert(WebPSharpYUVUpdateY != NULL); + assert(WebPSharpYUVUpdateRGB != NULL); + assert(WebPSharpYUVFilterRow != NULL); + rgba_to_yuv_last_cpuinfo_used = VP8GetCPUInfo; } diff --git a/3rdparty/libwebp/dsp/yuv.h b/3rdparty/libwebp/src/dsp/yuv.h similarity index 72% rename from 3rdparty/libwebp/dsp/yuv.h rename to 3rdparty/libwebp/src/dsp/yuv.h index 1d33b5863b..c8a55832d4 100644 --- a/3rdparty/libwebp/dsp/yuv.h +++ b/3rdparty/libwebp/src/dsp/yuv.h @@ -35,18 +35,8 @@ #ifndef WEBP_DSP_YUV_H_ #define WEBP_DSP_YUV_H_ -#include "./dsp.h" -#include "../dec/vp8_dec.h" - -#if defined(WEBP_EXPERIMENTAL_FEATURES) -// Do NOT activate this feature for real compression. This is only experimental! -// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace. -// This colorspace is close to Rec.601's Y'CbCr model with the notable -// difference of allowing larger range for luma/chroma. -// See http://en.wikipedia.org/wiki/YCbCr#JPEG_conversion paragraph, and its -// difference with http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion -// #define USE_YUVj -#endif +#include "src/dsp/dsp.h" +#include "src/dec/vp8_dec.h" //------------------------------------------------------------------------------ // YUV -> RGB conversion @@ -58,12 +48,8 @@ extern "C" { enum { YUV_FIX = 16, // fixed-point precision for RGB->YUV YUV_HALF = 1 << (YUV_FIX - 1), - YUV_MASK = (256 << YUV_FIX) - 1, - YUV_RANGE_MIN = -227, // min value of r/g/b output - YUV_RANGE_MAX = 256 + 226, // max value of r/g/b output YUV_FIX2 = 6, // fixed-point precision for YUV->RGB - YUV_HALF2 = 1 << YUV_FIX2 >> 1, YUV_MASK2 = (256 << YUV_FIX2) - 1 }; @@ -111,7 +97,7 @@ static WEBP_INLINE void VP8YuvToRgb565(int y, int u, int v, const int b = VP8YUVToB(y, u); // 5 usable bits const int rg = (r & 0xf8) | (g >> 5); const int gb = ((g << 3) & 0xe0) | (b >> 3); -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) rgb[0] = gb; rgb[1] = rg; #else @@ -127,7 +113,7 @@ static WEBP_INLINE void VP8YuvToRgba4444(int y, int u, int v, const int b = VP8YUVToB(y, u); // 4 usable bits const int rg = (r & 0xf0) | (g >> 4); const int ba = (b & 0xf0) | 0x0f; // overwrite the lower 4 bits -#ifdef WEBP_SWAP_16BIT_CSP +#if (WEBP_SWAP_16BIT_CSP == 1) argb[0] = ba; argb[1] = rg; #else @@ -157,29 +143,26 @@ static WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v, rgba[3] = 0xff; } -// Must be called before everything, to initialize the tables. -void VP8YUVInit(void); - //----------------------------------------------------------------------------- // SSE2 extra functions (mostly for upsampling_sse2.c) #if defined(WEBP_USE_SSE2) // Process 32 pixels and store the result (16b, 24b or 32b per pixel) in *dst. -void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToArgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); -void VP8YuvToRgba444432(const uint8_t* y, const uint8_t* u, const uint8_t* v, +void VP8YuvToRgba32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToRgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, uint8_t* dst); -void VP8YuvToRgb56532(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst); +void VP8YuvToBgra32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToBgr32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToArgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); +void VP8YuvToRgba444432_SSE2(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst); +void VP8YuvToRgb56532_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst); #endif // WEBP_USE_SSE2 @@ -192,8 +175,6 @@ static WEBP_INLINE int VP8ClipUV(int uv, int rounding) { return ((uv & ~0xff) == 0) ? uv : (uv < 0) ? 0 : 255; } -#ifndef USE_YUVj - static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) { const int luma = 16839 * r + 33059 * g + 6420 * b; return (luma + rounding + (16 << YUV_FIX)) >> YUV_FIX; // no need to clip @@ -209,28 +190,6 @@ static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) { return VP8ClipUV(v, rounding); } -#else - -// This JPEG-YUV colorspace, only for comparison! -// These are also 16bit precision coefficients from Rec.601, but with full -// [0..255] output range. -static WEBP_INLINE int VP8RGBToY(int r, int g, int b, int rounding) { - const int luma = 19595 * r + 38470 * g + 7471 * b; - return (luma + rounding) >> YUV_FIX; // no need to clip -} - -static WEBP_INLINE int VP8RGBToU(int r, int g, int b, int rounding) { - const int u = -11058 * r - 21710 * g + 32768 * b; - return VP8ClipUV(u, rounding); -} - -static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) { - const int v = 32768 * r - 27439 * g - 5329 * b; - return VP8ClipUV(v, rounding); -} - -#endif // USE_YUVj - #ifdef __cplusplus } // extern "C" #endif diff --git a/3rdparty/libwebp/dsp/yuv_mips32.c b/3rdparty/libwebp/src/dsp/yuv_mips32.c similarity index 92% rename from 3rdparty/libwebp/dsp/yuv_mips32.c rename to 3rdparty/libwebp/src/dsp/yuv_mips32.c index e61aac571f..9d0a887824 100644 --- a/3rdparty/libwebp/dsp/yuv_mips32.c +++ b/3rdparty/libwebp/src/dsp/yuv_mips32.c @@ -12,11 +12,11 @@ // Author(s): Djordje Pesut (djordje.pesut@imgtec.com) // Jovan Zelincevic (jovan.zelincevic@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS32) -#include "./yuv.h" +#include "src/dsp/yuv.h" //------------------------------------------------------------------------------ // simple point-sampling @@ -77,10 +77,10 @@ static void FUNC_NAME(const uint8_t* y, \ } \ } -ROW_FUNC(YuvToRgbRow, 3, 0, 1, 2, 0) -ROW_FUNC(YuvToRgbaRow, 4, 0, 1, 2, 3) -ROW_FUNC(YuvToBgrRow, 3, 2, 1, 0, 0) -ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3) +ROW_FUNC(YuvToRgbRow_MIPS32, 3, 0, 1, 2, 0) +ROW_FUNC(YuvToRgbaRow_MIPS32, 4, 0, 1, 2, 3) +ROW_FUNC(YuvToBgrRow_MIPS32, 3, 2, 1, 0, 0) +ROW_FUNC(YuvToBgraRow_MIPS32, 4, 2, 1, 0, 3) #undef ROW_FUNC @@ -90,10 +90,10 @@ ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3) extern void WebPInitSamplersMIPS32(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPS32(void) { - WebPSamplers[MODE_RGB] = YuvToRgbRow; - WebPSamplers[MODE_RGBA] = YuvToRgbaRow; - WebPSamplers[MODE_BGR] = YuvToBgrRow; - WebPSamplers[MODE_BGRA] = YuvToBgraRow; + WebPSamplers[MODE_RGB] = YuvToRgbRow_MIPS32; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow_MIPS32; + WebPSamplers[MODE_BGR] = YuvToBgrRow_MIPS32; + WebPSamplers[MODE_BGRA] = YuvToBgraRow_MIPS32; } #else // !WEBP_USE_MIPS32 diff --git a/3rdparty/libwebp/dsp/yuv_mips_dsp_r2.c b/3rdparty/libwebp/src/dsp/yuv_mips_dsp_r2.c similarity index 94% rename from 3rdparty/libwebp/dsp/yuv_mips_dsp_r2.c rename to 3rdparty/libwebp/src/dsp/yuv_mips_dsp_r2.c index 1720d4190f..cc8afcc756 100644 --- a/3rdparty/libwebp/dsp/yuv_mips_dsp_r2.c +++ b/3rdparty/libwebp/src/dsp/yuv_mips_dsp_r2.c @@ -12,11 +12,11 @@ // Author(s): Branimir Vasic (branimir.vasic@imgtec.com) // Djordje Pesut (djordje.pesut@imgtec.com) -#include "./dsp.h" +#include "src/dsp/dsp.h" #if defined(WEBP_USE_MIPS_DSP_R2) -#include "./yuv.h" +#include "src/dsp/yuv.h" //------------------------------------------------------------------------------ // simple point-sampling @@ -105,10 +105,10 @@ static void FUNC_NAME(const uint8_t* y, \ } \ } -ROW_FUNC(YuvToRgbRow, 3, 0, 1, 2, 0) -ROW_FUNC(YuvToRgbaRow, 4, 0, 1, 2, 3) -ROW_FUNC(YuvToBgrRow, 3, 2, 1, 0, 0) -ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3) +ROW_FUNC(YuvToRgbRow_MIPSdspR2, 3, 0, 1, 2, 0) +ROW_FUNC(YuvToRgbaRow_MIPSdspR2, 4, 0, 1, 2, 3) +ROW_FUNC(YuvToBgrRow_MIPSdspR2, 3, 2, 1, 0, 0) +ROW_FUNC(YuvToBgraRow_MIPSdspR2, 4, 2, 1, 0, 3) #undef ROW_FUNC #undef ASM_CLOBBER_LIST @@ -121,10 +121,10 @@ ROW_FUNC(YuvToBgraRow, 4, 2, 1, 0, 3) extern void WebPInitSamplersMIPSdspR2(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersMIPSdspR2(void) { - WebPSamplers[MODE_RGB] = YuvToRgbRow; - WebPSamplers[MODE_RGBA] = YuvToRgbaRow; - WebPSamplers[MODE_BGR] = YuvToBgrRow; - WebPSamplers[MODE_BGRA] = YuvToBgraRow; + WebPSamplers[MODE_RGB] = YuvToRgbRow_MIPSdspR2; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow_MIPSdspR2; + WebPSamplers[MODE_BGR] = YuvToBgrRow_MIPSdspR2; + WebPSamplers[MODE_BGRA] = YuvToBgraRow_MIPSdspR2; } #else // !WEBP_USE_MIPS_DSP_R2 diff --git a/3rdparty/libwebp/src/dsp/yuv_neon.c b/3rdparty/libwebp/src/dsp/yuv_neon.c new file mode 100644 index 0000000000..a34d60248f --- /dev/null +++ b/3rdparty/libwebp/src/dsp/yuv_neon.c @@ -0,0 +1,288 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// YUV->RGB conversion functions +// +// Author: Skal (pascal.massimino@gmail.com) + +#include "src/dsp/yuv.h" + +#if defined(WEBP_USE_NEON) + +#include +#include + +#include "src/dsp/neon.h" + +//----------------------------------------------------------------------------- + +static uint8x8_t ConvertRGBToY_NEON(const uint8x8_t R, + const uint8x8_t G, + const uint8x8_t B) { + const uint16x8_t r = vmovl_u8(R); + const uint16x8_t g = vmovl_u8(G); + const uint16x8_t b = vmovl_u8(B); + const uint16x4_t r_lo = vget_low_u16(r); + const uint16x4_t r_hi = vget_high_u16(r); + const uint16x4_t g_lo = vget_low_u16(g); + const uint16x4_t g_hi = vget_high_u16(g); + const uint16x4_t b_lo = vget_low_u16(b); + const uint16x4_t b_hi = vget_high_u16(b); + const uint32x4_t tmp0_lo = vmull_n_u16( r_lo, 16839u); + const uint32x4_t tmp0_hi = vmull_n_u16( r_hi, 16839u); + const uint32x4_t tmp1_lo = vmlal_n_u16(tmp0_lo, g_lo, 33059u); + const uint32x4_t tmp1_hi = vmlal_n_u16(tmp0_hi, g_hi, 33059u); + const uint32x4_t tmp2_lo = vmlal_n_u16(tmp1_lo, b_lo, 6420u); + const uint32x4_t tmp2_hi = vmlal_n_u16(tmp1_hi, b_hi, 6420u); + const uint16x8_t Y1 = vcombine_u16(vrshrn_n_u32(tmp2_lo, 16), + vrshrn_n_u32(tmp2_hi, 16)); + const uint16x8_t Y2 = vaddq_u16(Y1, vdupq_n_u16(16)); + return vqmovn_u16(Y2); +} + +static void ConvertRGB24ToY_NEON(const uint8_t* rgb, uint8_t* y, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8, rgb += 3 * 8) { + const uint8x8x3_t RGB = vld3_u8(rgb); + const uint8x8_t Y = ConvertRGBToY_NEON(RGB.val[0], RGB.val[1], RGB.val[2]); + vst1_u8(y + i, Y); + } + for (; i < width; ++i, rgb += 3) { // left-over + y[i] = VP8RGBToY(rgb[0], rgb[1], rgb[2], YUV_HALF); + } +} + +static void ConvertBGR24ToY_NEON(const uint8_t* bgr, uint8_t* y, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8, bgr += 3 * 8) { + const uint8x8x3_t BGR = vld3_u8(bgr); + const uint8x8_t Y = ConvertRGBToY_NEON(BGR.val[2], BGR.val[1], BGR.val[0]); + vst1_u8(y + i, Y); + } + for (; i < width; ++i, bgr += 3) { // left-over + y[i] = VP8RGBToY(bgr[2], bgr[1], bgr[0], YUV_HALF); + } +} + +static void ConvertARGBToY_NEON(const uint32_t* argb, uint8_t* y, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8) { + const uint8x8x4_t RGB = vld4_u8((const uint8_t*)&argb[i]); + const uint8x8_t Y = ConvertRGBToY_NEON(RGB.val[2], RGB.val[1], RGB.val[0]); + vst1_u8(y + i, Y); + } + for (; i < width; ++i) { // left-over + const uint32_t p = argb[i]; + y[i] = VP8RGBToY((p >> 16) & 0xff, (p >> 8) & 0xff, (p >> 0) & 0xff, + YUV_HALF); + } +} + +//----------------------------------------------------------------------------- + +// computes: DST_s16 = [(C0 * r + C1 * g + C2 * b) >> 16] + CST +#define MULTIPLY_16b_PREAMBLE(r, g, b) \ + const int16x4_t r_lo = vreinterpret_s16_u16(vget_low_u16(r)); \ + const int16x4_t r_hi = vreinterpret_s16_u16(vget_high_u16(r)); \ + const int16x4_t g_lo = vreinterpret_s16_u16(vget_low_u16(g)); \ + const int16x4_t g_hi = vreinterpret_s16_u16(vget_high_u16(g)); \ + const int16x4_t b_lo = vreinterpret_s16_u16(vget_low_u16(b)); \ + const int16x4_t b_hi = vreinterpret_s16_u16(vget_high_u16(b)) + +#define MULTIPLY_16b(C0, C1, C2, CST, DST_s16) do { \ + const int32x4_t tmp0_lo = vmull_n_s16( r_lo, C0); \ + const int32x4_t tmp0_hi = vmull_n_s16( r_hi, C0); \ + const int32x4_t tmp1_lo = vmlal_n_s16(tmp0_lo, g_lo, C1); \ + const int32x4_t tmp1_hi = vmlal_n_s16(tmp0_hi, g_hi, C1); \ + const int32x4_t tmp2_lo = vmlal_n_s16(tmp1_lo, b_lo, C2); \ + const int32x4_t tmp2_hi = vmlal_n_s16(tmp1_hi, b_hi, C2); \ + const int16x8_t tmp3 = vcombine_s16(vshrn_n_s32(tmp2_lo, 16), \ + vshrn_n_s32(tmp2_hi, 16)); \ + DST_s16 = vaddq_s16(tmp3, vdupq_n_s16(CST)); \ +} while (0) + +// This needs to be a macro, since (128 << SHIFT) needs to be an immediate. +#define CONVERT_RGB_TO_UV(r, g, b, SHIFT, U_DST, V_DST) do { \ + MULTIPLY_16b_PREAMBLE(r, g, b); \ + MULTIPLY_16b(-9719, -19081, 28800, 128 << SHIFT, U_DST); \ + MULTIPLY_16b(28800, -24116, -4684, 128 << SHIFT, V_DST); \ +} while (0) + +static void ConvertRGBA32ToUV_NEON(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width) { + int i; + for (i = 0; i + 8 <= width; i += 8, rgb += 4 * 8) { + const uint16x8x4_t RGB = vld4q_u16((const uint16_t*)rgb); + int16x8_t U, V; + CONVERT_RGB_TO_UV(RGB.val[0], RGB.val[1], RGB.val[2], 2, U, V); + vst1_u8(u + i, vqrshrun_n_s16(U, 2)); + vst1_u8(v + i, vqrshrun_n_s16(V, 2)); + } + for (; i < width; i += 1, rgb += 4) { + const int r = rgb[0], g = rgb[1], b = rgb[2]; + u[i] = VP8RGBToU(r, g, b, YUV_HALF << 2); + v[i] = VP8RGBToV(r, g, b, YUV_HALF << 2); + } +} + +static void ConvertARGBToUV_NEON(const uint32_t* argb, uint8_t* u, uint8_t* v, + int src_width, int do_store) { + int i; + for (i = 0; i + 16 <= src_width; i += 16, u += 8, v += 8) { + const uint8x16x4_t RGB = vld4q_u8((const uint8_t*)&argb[i]); + const uint16x8_t R = vpaddlq_u8(RGB.val[2]); // pair-wise adds + const uint16x8_t G = vpaddlq_u8(RGB.val[1]); + const uint16x8_t B = vpaddlq_u8(RGB.val[0]); + int16x8_t U_tmp, V_tmp; + CONVERT_RGB_TO_UV(R, G, B, 1, U_tmp, V_tmp); + { + const uint8x8_t U = vqrshrun_n_s16(U_tmp, 1); + const uint8x8_t V = vqrshrun_n_s16(V_tmp, 1); + if (do_store) { + vst1_u8(u, U); + vst1_u8(v, V); + } else { + const uint8x8_t prev_u = vld1_u8(u); + const uint8x8_t prev_v = vld1_u8(v); + vst1_u8(u, vrhadd_u8(U, prev_u)); + vst1_u8(v, vrhadd_u8(V, prev_v)); + } + } + } + if (i < src_width) { // left-over + WebPConvertARGBToUV_C(argb + i, u, v, src_width - i, do_store); + } +} + + +//------------------------------------------------------------------------------ + +extern void WebPInitConvertARGBToYUVNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVNEON(void) { + WebPConvertRGB24ToY = ConvertRGB24ToY_NEON; + WebPConvertBGR24ToY = ConvertBGR24ToY_NEON; + WebPConvertARGBToY = ConvertARGBToY_NEON; + WebPConvertARGBToUV = ConvertARGBToUV_NEON; + WebPConvertRGBA32ToUV = ConvertRGBA32ToUV_NEON; +} + +//------------------------------------------------------------------------------ + +#define MAX_Y ((1 << 10) - 1) // 10b precision over 16b-arithmetic +static uint16_t clip_y_NEON(int v) { + return (v < 0) ? 0 : (v > MAX_Y) ? MAX_Y : (uint16_t)v; +} + +static uint64_t SharpYUVUpdateY_NEON(const uint16_t* ref, const uint16_t* src, + uint16_t* dst, int len) { + int i; + const int16x8_t zero = vdupq_n_s16(0); + const int16x8_t max = vdupq_n_s16(MAX_Y); + uint64x2_t sum = vdupq_n_u64(0); + uint64_t diff; + + for (i = 0; i + 8 <= len; i += 8) { + const int16x8_t A = vreinterpretq_s16_u16(vld1q_u16(ref + i)); + const int16x8_t B = vreinterpretq_s16_u16(vld1q_u16(src + i)); + const int16x8_t C = vreinterpretq_s16_u16(vld1q_u16(dst + i)); + const int16x8_t D = vsubq_s16(A, B); // diff_y + const int16x8_t F = vaddq_s16(C, D); // new_y + const uint16x8_t H = + vreinterpretq_u16_s16(vmaxq_s16(vminq_s16(F, max), zero)); + const int16x8_t I = vabsq_s16(D); // abs(diff_y) + vst1q_u16(dst + i, H); + sum = vpadalq_u32(sum, vpaddlq_u16(vreinterpretq_u16_s16(I))); + } + diff = vgetq_lane_u64(sum, 0) + vgetq_lane_u64(sum, 1); + for (; i < len; ++i) { + const int diff_y = ref[i] - src[i]; + const int new_y = (int)(dst[i]) + diff_y; + dst[i] = clip_y_NEON(new_y); + diff += (uint64_t)(abs(diff_y)); + } + return diff; +} + +static void SharpYUVUpdateRGB_NEON(const int16_t* ref, const int16_t* src, + int16_t* dst, int len) { + int i; + for (i = 0; i + 8 <= len; i += 8) { + const int16x8_t A = vld1q_s16(ref + i); + const int16x8_t B = vld1q_s16(src + i); + const int16x8_t C = vld1q_s16(dst + i); + const int16x8_t D = vsubq_s16(A, B); // diff_uv + const int16x8_t E = vaddq_s16(C, D); // new_uv + vst1q_s16(dst + i, E); + } + for (; i < len; ++i) { + const int diff_uv = ref[i] - src[i]; + dst[i] += diff_uv; + } +} + +static void SharpYUVFilterRow_NEON(const int16_t* A, const int16_t* B, int len, + const uint16_t* best_y, uint16_t* out) { + int i; + const int16x8_t max = vdupq_n_s16(MAX_Y); + const int16x8_t zero = vdupq_n_s16(0); + for (i = 0; i + 8 <= len; i += 8) { + const int16x8_t a0 = vld1q_s16(A + i + 0); + const int16x8_t a1 = vld1q_s16(A + i + 1); + const int16x8_t b0 = vld1q_s16(B + i + 0); + const int16x8_t b1 = vld1q_s16(B + i + 1); + const int16x8_t a0b1 = vaddq_s16(a0, b1); + const int16x8_t a1b0 = vaddq_s16(a1, b0); + const int16x8_t a0a1b0b1 = vaddq_s16(a0b1, a1b0); // A0+A1+B0+B1 + const int16x8_t a0b1_2 = vaddq_s16(a0b1, a0b1); // 2*(A0+B1) + const int16x8_t a1b0_2 = vaddq_s16(a1b0, a1b0); // 2*(A1+B0) + const int16x8_t c0 = vshrq_n_s16(vaddq_s16(a0b1_2, a0a1b0b1), 3); + const int16x8_t c1 = vshrq_n_s16(vaddq_s16(a1b0_2, a0a1b0b1), 3); + const int16x8_t d0 = vaddq_s16(c1, a0); + const int16x8_t d1 = vaddq_s16(c0, a1); + const int16x8_t e0 = vrshrq_n_s16(d0, 1); + const int16x8_t e1 = vrshrq_n_s16(d1, 1); + const int16x8x2_t f = vzipq_s16(e0, e1); + const int16x8_t g0 = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i + 0)); + const int16x8_t g1 = vreinterpretq_s16_u16(vld1q_u16(best_y + 2 * i + 8)); + const int16x8_t h0 = vaddq_s16(g0, f.val[0]); + const int16x8_t h1 = vaddq_s16(g1, f.val[1]); + const int16x8_t i0 = vmaxq_s16(vminq_s16(h0, max), zero); + const int16x8_t i1 = vmaxq_s16(vminq_s16(h1, max), zero); + vst1q_u16(out + 2 * i + 0, vreinterpretq_u16_s16(i0)); + vst1q_u16(out + 2 * i + 8, vreinterpretq_u16_s16(i1)); + } + for (; i < len; ++i) { + const int a0b1 = A[i + 0] + B[i + 1]; + const int a1b0 = A[i + 1] + B[i + 0]; + const int a0a1b0b1 = a0b1 + a1b0 + 8; + const int v0 = (8 * A[i + 0] + 2 * a1b0 + a0a1b0b1) >> 4; + const int v1 = (8 * A[i + 1] + 2 * a0b1 + a0a1b0b1) >> 4; + out[2 * i + 0] = clip_y_NEON(best_y[2 * i + 0] + v0); + out[2 * i + 1] = clip_y_NEON(best_y[2 * i + 1] + v1); + } +} +#undef MAX_Y + +//------------------------------------------------------------------------------ + +extern void WebPInitSharpYUVNEON(void); + +WEBP_TSAN_IGNORE_FUNCTION void WebPInitSharpYUVNEON(void) { + WebPSharpYUVUpdateY = SharpYUVUpdateY_NEON; + WebPSharpYUVUpdateRGB = SharpYUVUpdateRGB_NEON; + WebPSharpYUVFilterRow = SharpYUVFilterRow_NEON; +} + +#else // !WEBP_USE_NEON + +WEBP_DSP_INIT_STUB(WebPInitConvertARGBToYUVNEON) +WEBP_DSP_INIT_STUB(WebPInitSharpYUVNEON) + +#endif // WEBP_USE_NEON diff --git a/3rdparty/libwebp/dsp/yuv_sse2.c b/3rdparty/libwebp/src/dsp/yuv_sse2.c similarity index 70% rename from 3rdparty/libwebp/dsp/yuv_sse2.c rename to 3rdparty/libwebp/src/dsp/yuv_sse2.c index e33c2bbafd..6810bf8d15 100644 --- a/3rdparty/libwebp/dsp/yuv_sse2.c +++ b/3rdparty/libwebp/src/dsp/yuv_sse2.c @@ -11,11 +11,11 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./yuv.h" +#include "src/dsp/yuv.h" #if defined(WEBP_USE_SSE2) -#include "./common_sse2.h" +#include "src/dsp/common_sse2.h" #include #include @@ -26,12 +26,12 @@ // R = (19077 * y + 26149 * v - 14234) >> 6 // G = (19077 * y - 6419 * u - 13320 * v + 8708) >> 6 // B = (19077 * y + 33050 * u - 17685) >> 6 -static void ConvertYUV444ToRGB(const __m128i* const Y0, - const __m128i* const U0, - const __m128i* const V0, - __m128i* const R, - __m128i* const G, - __m128i* const B) { +static void ConvertYUV444ToRGB_SSE2(const __m128i* const Y0, + const __m128i* const U0, + const __m128i* const V0, + __m128i* const R, + __m128i* const G, + __m128i* const B) { const __m128i k19077 = _mm_set1_epi16(19077); const __m128i k26149 = _mm_set1_epi16(26149); const __m128i k14234 = _mm_set1_epi16(14234); @@ -66,13 +66,13 @@ static void ConvertYUV444ToRGB(const __m128i* const Y0, } // Load the bytes into the *upper* part of 16b words. That's "<< 8", basically. -static WEBP_INLINE __m128i Load_HI_16(const uint8_t* src) { +static WEBP_INLINE __m128i Load_HI_16_SSE2(const uint8_t* src) { const __m128i zero = _mm_setzero_si128(); return _mm_unpacklo_epi8(zero, _mm_loadl_epi64((const __m128i*)src)); } // Load and replicate the U/V samples -static WEBP_INLINE __m128i Load_UV_HI_8(const uint8_t* src) { +static WEBP_INLINE __m128i Load_UV_HI_8_SSE2(const uint8_t* src) { const __m128i zero = _mm_setzero_si128(); const __m128i tmp0 = _mm_cvtsi32_si128(*(const uint32_t*)src); const __m128i tmp1 = _mm_unpacklo_epi8(zero, tmp0); @@ -80,29 +80,33 @@ static WEBP_INLINE __m128i Load_UV_HI_8(const uint8_t* src) { } // Convert 32 samples of YUV444 to R/G/B -static void YUV444ToRGB(const uint8_t* const y, - const uint8_t* const u, - const uint8_t* const v, - __m128i* const R, __m128i* const G, __m128i* const B) { - const __m128i Y0 = Load_HI_16(y), U0 = Load_HI_16(u), V0 = Load_HI_16(v); - ConvertYUV444ToRGB(&Y0, &U0, &V0, R, G, B); +static void YUV444ToRGB_SSE2(const uint8_t* const y, + const uint8_t* const u, + const uint8_t* const v, + __m128i* const R, __m128i* const G, + __m128i* const B) { + const __m128i Y0 = Load_HI_16_SSE2(y), U0 = Load_HI_16_SSE2(u), + V0 = Load_HI_16_SSE2(v); + ConvertYUV444ToRGB_SSE2(&Y0, &U0, &V0, R, G, B); } // Convert 32 samples of YUV420 to R/G/B -static void YUV420ToRGB(const uint8_t* const y, - const uint8_t* const u, - const uint8_t* const v, - __m128i* const R, __m128i* const G, __m128i* const B) { - const __m128i Y0 = Load_HI_16(y), U0 = Load_UV_HI_8(u), V0 = Load_UV_HI_8(v); - ConvertYUV444ToRGB(&Y0, &U0, &V0, R, G, B); +static void YUV420ToRGB_SSE2(const uint8_t* const y, + const uint8_t* const u, + const uint8_t* const v, + __m128i* const R, __m128i* const G, + __m128i* const B) { + const __m128i Y0 = Load_HI_16_SSE2(y), U0 = Load_UV_HI_8_SSE2(u), + V0 = Load_UV_HI_8_SSE2(v); + ConvertYUV444ToRGB_SSE2(&Y0, &U0, &V0, R, G, B); } // Pack R/G/B/A results into 32b output. -static WEBP_INLINE void PackAndStore4(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - const __m128i* const A, - uint8_t* const dst) { +static WEBP_INLINE void PackAndStore4_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + const __m128i* const A, + uint8_t* const dst) { const __m128i rb = _mm_packus_epi16(*R, *B); const __m128i ga = _mm_packus_epi16(*G, *A); const __m128i rg = _mm_unpacklo_epi8(rb, ga); @@ -114,12 +118,12 @@ static WEBP_INLINE void PackAndStore4(const __m128i* const R, } // Pack R/G/B/A results into 16b output. -static WEBP_INLINE void PackAndStore4444(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - const __m128i* const A, - uint8_t* const dst) { -#if !defined(WEBP_SWAP_16BIT_CSP) +static WEBP_INLINE void PackAndStore4444_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + const __m128i* const A, + uint8_t* const dst) { +#if (WEBP_SWAP_16BIT_CSP == 0) const __m128i rg0 = _mm_packus_epi16(*R, *G); const __m128i ba0 = _mm_packus_epi16(*B, *A); #else @@ -136,10 +140,10 @@ static WEBP_INLINE void PackAndStore4444(const __m128i* const R, } // Pack R/G/B results into 16b output. -static WEBP_INLINE void PackAndStore565(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - uint8_t* const dst) { +static WEBP_INLINE void PackAndStore565_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + uint8_t* const dst) { const __m128i r0 = _mm_packus_epi16(*R, *R); const __m128i g0 = _mm_packus_epi16(*G, *G); const __m128i b0 = _mm_packus_epi16(*B, *B); @@ -149,7 +153,7 @@ static WEBP_INLINE void PackAndStore565(const __m128i* const R, const __m128i g2 = _mm_slli_epi16(_mm_and_si128(g0, _mm_set1_epi8(0x1c)), 3); const __m128i rg = _mm_or_si128(r1, g1); const __m128i gb = _mm_or_si128(g2, b1); -#if !defined(WEBP_SWAP_16BIT_CSP) +#if (WEBP_SWAP_16BIT_CSP == 0) const __m128i rgb565 = _mm_unpacklo_epi8(rg, gb); #else const __m128i rgb565 = _mm_unpacklo_epi8(gb, rg); @@ -160,10 +164,10 @@ static WEBP_INLINE void PackAndStore565(const __m128i* const R, // Pack the planar buffers // rrrr... rrrr... gggg... gggg... bbbb... bbbb.... // triplet by triplet in the output buffer rgb as rgbrgbrgbrgb ... -static WEBP_INLINE void PlanarTo24b(__m128i* const in0, __m128i* const in1, - __m128i* const in2, __m128i* const in3, - __m128i* const in4, __m128i* const in5, - uint8_t* const rgb) { +static WEBP_INLINE void PlanarTo24b_SSE2(__m128i* const in0, __m128i* const in1, + __m128i* const in2, __m128i* const in3, + __m128i* const in4, __m128i* const in5, + uint8_t* const rgb) { // The input is 6 registers of sixteen 8b but for the sake of explanation, // let's take 6 registers of four 8b values. // To pack, we will keep taking one every two 8b integer and move it @@ -186,69 +190,69 @@ static WEBP_INLINE void PlanarTo24b(__m128i* const in0, __m128i* const in1, _mm_storeu_si128((__m128i*)(rgb + 80), *in5); } -void VP8YuvToRgba32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { +void VP8YuvToRgba32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { const __m128i kAlpha = _mm_set1_epi16(255); int n; for (n = 0; n < 32; n += 8, dst += 32) { __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4(&R, &G, &B, &kAlpha, dst); + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4_SSE2(&R, &G, &B, &kAlpha, dst); } } -void VP8YuvToBgra32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { +void VP8YuvToBgra32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { const __m128i kAlpha = _mm_set1_epi16(255); int n; for (n = 0; n < 32; n += 8, dst += 32) { __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4(&B, &G, &R, &kAlpha, dst); + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4_SSE2(&B, &G, &R, &kAlpha, dst); } } -void VP8YuvToArgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { +void VP8YuvToArgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { const __m128i kAlpha = _mm_set1_epi16(255); int n; for (n = 0; n < 32; n += 8, dst += 32) { __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4(&kAlpha, &R, &G, &B, dst); + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4_SSE2(&kAlpha, &R, &G, &B, dst); } } -void VP8YuvToRgba444432(const uint8_t* y, const uint8_t* u, const uint8_t* v, +void VP8YuvToRgba444432_SSE2(const uint8_t* y, const uint8_t* u, + const uint8_t* v, uint8_t* dst) { + const __m128i kAlpha = _mm_set1_epi16(255); + int n; + for (n = 0; n < 32; n += 8, dst += 16) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore4444_SSE2(&R, &G, &B, &kAlpha, dst); + } +} + +void VP8YuvToRgb56532_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { + int n; + for (n = 0; n < 32; n += 8, dst += 16) { + __m128i R, G, B; + YUV444ToRGB_SSE2(y + n, u + n, v + n, &R, &G, &B); + PackAndStore565_SSE2(&R, &G, &B, dst); + } +} + +void VP8YuvToRgb32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, uint8_t* dst) { - const __m128i kAlpha = _mm_set1_epi16(255); - int n; - for (n = 0; n < 32; n += 8, dst += 16) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore4444(&R, &G, &B, &kAlpha, dst); - } -} - -void VP8YuvToRgb56532(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { - int n; - for (n = 0; n < 32; n += 8, dst += 16) { - __m128i R, G, B; - YUV444ToRGB(y + n, u + n, v + n, &R, &G, &B); - PackAndStore565(&R, &G, &B, dst); - } -} - -void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5; - YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1); - YUV444ToRGB(y + 16, u + 16, v + 16, &R2, &G2, &B2); - YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3); + YUV444ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV444ToRGB_SSE2(y + 8, u + 8, v + 8, &R1, &G1, &B1); + YUV444ToRGB_SSE2(y + 16, u + 16, v + 16, &R2, &G2, &B2); + YUV444ToRGB_SSE2(y + 24, u + 24, v + 24, &R3, &G3, &B3); // Cast to 8b and store as RRRRGGGGBBBB. rgb0 = _mm_packus_epi16(R0, R1); @@ -259,18 +263,18 @@ void VP8YuvToRgb32(const uint8_t* y, const uint8_t* u, const uint8_t* v, rgb5 = _mm_packus_epi16(B2, B3); // Pack as RGBRGBRGBRGB. - PlanarTo24b(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); + PlanarTo24b_SSE2(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); } -void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst) { +void VP8YuvToBgr32_SSE2(const uint8_t* y, const uint8_t* u, const uint8_t* v, + uint8_t* dst) { __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5; - YUV444ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV444ToRGB(y + 8, u + 8, v + 8, &R1, &G1, &B1); - YUV444ToRGB(y + 16, u + 16, v + 16, &R2, &G2, &B2); - YUV444ToRGB(y + 24, u + 24, v + 24, &R3, &G3, &B3); + YUV444ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV444ToRGB_SSE2(y + 8, u + 8, v + 8, &R1, &G1, &B1); + YUV444ToRGB_SSE2(y + 16, u + 16, v + 16, &R2, &G2, &B2); + YUV444ToRGB_SSE2(y + 24, u + 24, v + 24, &R3, &G3, &B3); // Cast to 8b and store as BBBBGGGGRRRR. bgr0 = _mm_packus_epi16(B0, B1); @@ -281,20 +285,21 @@ void VP8YuvToBgr32(const uint8_t* y, const uint8_t* u, const uint8_t* v, bgr5= _mm_packus_epi16(R2, R3); // Pack as BGRBGRBGRBGR. - PlanarTo24b(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); + PlanarTo24b_SSE2(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); } //----------------------------------------------------------------------------- // Arbitrary-length row conversion functions -static void YuvToRgbaRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { +static void YuvToRgbaRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { const __m128i kAlpha = _mm_set1_epi16(255); int n; for (n = 0; n + 8 <= len; n += 8, dst += 32) { __m128i R, G, B; - YUV420ToRGB(y, u, v, &R, &G, &B); - PackAndStore4(&R, &G, &B, &kAlpha, dst); + YUV420ToRGB_SSE2(y, u, v, &R, &G, &B); + PackAndStore4_SSE2(&R, &G, &B, &kAlpha, dst); y += 8; u += 4; v += 4; @@ -308,14 +313,15 @@ static void YuvToRgbaRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, } } -static void YuvToBgraRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { +static void YuvToBgraRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { const __m128i kAlpha = _mm_set1_epi16(255); int n; for (n = 0; n + 8 <= len; n += 8, dst += 32) { __m128i R, G, B; - YUV420ToRGB(y, u, v, &R, &G, &B); - PackAndStore4(&B, &G, &R, &kAlpha, dst); + YUV420ToRGB_SSE2(y, u, v, &R, &G, &B); + PackAndStore4_SSE2(&B, &G, &R, &kAlpha, dst); y += 8; u += 4; v += 4; @@ -329,14 +335,15 @@ static void YuvToBgraRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, } } -static void YuvToArgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { +static void YuvToArgbRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { const __m128i kAlpha = _mm_set1_epi16(255); int n; for (n = 0; n + 8 <= len; n += 8, dst += 32) { __m128i R, G, B; - YUV420ToRGB(y, u, v, &R, &G, &B); - PackAndStore4(&kAlpha, &R, &G, &B, dst); + YUV420ToRGB_SSE2(y, u, v, &R, &G, &B); + PackAndStore4_SSE2(&kAlpha, &R, &G, &B, dst); y += 8; u += 4; v += 4; @@ -350,17 +357,18 @@ static void YuvToArgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, } } -static void YuvToRgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { +static void YuvToRgbRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { int n; for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; __m128i rgb0, rgb1, rgb2, rgb3, rgb4, rgb5; - YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1); - YUV420ToRGB(y + 16, u + 8, v + 8, &R2, &G2, &B2); - YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3); + YUV420ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV420ToRGB_SSE2(y + 8, u + 4, v + 4, &R1, &G1, &B1); + YUV420ToRGB_SSE2(y + 16, u + 8, v + 8, &R2, &G2, &B2); + YUV420ToRGB_SSE2(y + 24, u + 12, v + 12, &R3, &G3, &B3); // Cast to 8b and store as RRRRGGGGBBBB. rgb0 = _mm_packus_epi16(R0, R1); @@ -371,7 +379,7 @@ static void YuvToRgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, rgb5 = _mm_packus_epi16(B2, B3); // Pack as RGBRGBRGBRGB. - PlanarTo24b(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); + PlanarTo24b_SSE2(&rgb0, &rgb1, &rgb2, &rgb3, &rgb4, &rgb5, dst); y += 32; u += 16; @@ -386,17 +394,18 @@ static void YuvToRgbRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, } } -static void YuvToBgrRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, - uint8_t* dst, int len) { +static void YuvToBgrRow_SSE2(const uint8_t* y, + const uint8_t* u, const uint8_t* v, + uint8_t* dst, int len) { int n; for (n = 0; n + 32 <= len; n += 32, dst += 32 * 3) { __m128i R0, R1, R2, R3, G0, G1, G2, G3, B0, B1, B2, B3; __m128i bgr0, bgr1, bgr2, bgr3, bgr4, bgr5; - YUV420ToRGB(y + 0, u + 0, v + 0, &R0, &G0, &B0); - YUV420ToRGB(y + 8, u + 4, v + 4, &R1, &G1, &B1); - YUV420ToRGB(y + 16, u + 8, v + 8, &R2, &G2, &B2); - YUV420ToRGB(y + 24, u + 12, v + 12, &R3, &G3, &B3); + YUV420ToRGB_SSE2(y + 0, u + 0, v + 0, &R0, &G0, &B0); + YUV420ToRGB_SSE2(y + 8, u + 4, v + 4, &R1, &G1, &B1); + YUV420ToRGB_SSE2(y + 16, u + 8, v + 8, &R2, &G2, &B2); + YUV420ToRGB_SSE2(y + 24, u + 12, v + 12, &R3, &G3, &B3); // Cast to 8b and store as BBBBGGGGRRRR. bgr0 = _mm_packus_epi16(B0, B1); @@ -407,7 +416,7 @@ static void YuvToBgrRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, bgr5 = _mm_packus_epi16(R2, R3); // Pack as BGRBGRBGRBGR. - PlanarTo24b(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); + PlanarTo24b_SSE2(&bgr0, &bgr1, &bgr2, &bgr3, &bgr4, &bgr5, dst); y += 32; u += 16; @@ -428,11 +437,11 @@ static void YuvToBgrRow(const uint8_t* y, const uint8_t* u, const uint8_t* v, extern void WebPInitSamplersSSE2(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE2(void) { - WebPSamplers[MODE_RGB] = YuvToRgbRow; - WebPSamplers[MODE_RGBA] = YuvToRgbaRow; - WebPSamplers[MODE_BGR] = YuvToBgrRow; - WebPSamplers[MODE_BGRA] = YuvToBgraRow; - WebPSamplers[MODE_ARGB] = YuvToArgbRow; + WebPSamplers[MODE_RGB] = YuvToRgbRow_SSE2; + WebPSamplers[MODE_RGBA] = YuvToRgbaRow_SSE2; + WebPSamplers[MODE_BGR] = YuvToBgrRow_SSE2; + WebPSamplers[MODE_BGRA] = YuvToBgraRow_SSE2; + WebPSamplers[MODE_ARGB] = YuvToArgbRow_SSE2; } //------------------------------------------------------------------------------ @@ -445,7 +454,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPInitSamplersSSE2(void) { // Function that inserts a value of the second half of the in buffer in between // every two char of the first half. -static WEBP_INLINE void RGB24PackedToPlanarHelper( +static WEBP_INLINE void RGB24PackedToPlanarHelper_SSE2( const __m128i* const in /*in[6]*/, __m128i* const out /*out[6]*/) { out[0] = _mm_unpacklo_epi8(in[0], in[3]); out[1] = _mm_unpackhi_epi8(in[0], in[3]); @@ -458,8 +467,8 @@ static WEBP_INLINE void RGB24PackedToPlanarHelper( // Unpack the 8b input rgbrgbrgbrgb ... as contiguous registers: // rrrr... rrrr... gggg... gggg... bbbb... bbbb.... // Similar to PlanarTo24bHelper(), but in reverse order. -static WEBP_INLINE void RGB24PackedToPlanar(const uint8_t* const rgb, - __m128i* const out /*out[6]*/) { +static WEBP_INLINE void RGB24PackedToPlanar_SSE2( + const uint8_t* const rgb, __m128i* const out /*out[6]*/) { __m128i tmp[6]; tmp[0] = _mm_loadu_si128((const __m128i*)(rgb + 0)); tmp[1] = _mm_loadu_si128((const __m128i*)(rgb + 16)); @@ -468,16 +477,16 @@ static WEBP_INLINE void RGB24PackedToPlanar(const uint8_t* const rgb, tmp[4] = _mm_loadu_si128((const __m128i*)(rgb + 64)); tmp[5] = _mm_loadu_si128((const __m128i*)(rgb + 80)); - RGB24PackedToPlanarHelper(tmp, out); - RGB24PackedToPlanarHelper(out, tmp); - RGB24PackedToPlanarHelper(tmp, out); - RGB24PackedToPlanarHelper(out, tmp); - RGB24PackedToPlanarHelper(tmp, out); + RGB24PackedToPlanarHelper_SSE2(tmp, out); + RGB24PackedToPlanarHelper_SSE2(out, tmp); + RGB24PackedToPlanarHelper_SSE2(tmp, out); + RGB24PackedToPlanarHelper_SSE2(out, tmp); + RGB24PackedToPlanarHelper_SSE2(tmp, out); } // Convert 8 packed ARGB to r[], g[], b[] -static WEBP_INLINE void RGB32PackedToPlanar(const uint32_t* const argb, - __m128i* const rgb /*in[6]*/) { +static WEBP_INLINE void RGB32PackedToPlanar_SSE2(const uint32_t* const argb, + __m128i* const rgb /*in[6]*/) { const __m128i zero = _mm_setzero_si128(); __m128i a0 = LOAD_16(argb + 0); __m128i a1 = LOAD_16(argb + 4); @@ -511,10 +520,10 @@ static WEBP_INLINE void RGB32PackedToPlanar(const uint32_t* const argb, } while (0) #define MK_CST_16(A, B) _mm_set_epi16((B), (A), (B), (A), (B), (A), (B), (A)) -static WEBP_INLINE void ConvertRGBToY(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - __m128i* const Y) { +static WEBP_INLINE void ConvertRGBToY_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + __m128i* const Y) { const __m128i kRG_y = MK_CST_16(16839, 33059 - 16384); const __m128i kGB_y = MK_CST_16(16384, 6420); const __m128i kHALF_Y = _mm_set1_epi32((16 << YUV_FIX) + YUV_HALF); @@ -526,10 +535,11 @@ static WEBP_INLINE void ConvertRGBToY(const __m128i* const R, TRANSFORM(RG_lo, RG_hi, GB_lo, GB_hi, kRG_y, kGB_y, kHALF_Y, YUV_FIX, *Y); } -static WEBP_INLINE void ConvertRGBToUV(const __m128i* const R, - const __m128i* const G, - const __m128i* const B, - __m128i* const U, __m128i* const V) { +static WEBP_INLINE void ConvertRGBToUV_SSE2(const __m128i* const R, + const __m128i* const G, + const __m128i* const B, + __m128i* const U, + __m128i* const V) { const __m128i kRG_u = MK_CST_16(-9719, -19081); const __m128i kGB_u = MK_CST_16(0, 28800); const __m128i kRG_v = MK_CST_16(28800, 0); @@ -549,14 +559,14 @@ static WEBP_INLINE void ConvertRGBToUV(const __m128i* const R, #undef MK_CST_16 #undef TRANSFORM -static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) { +static void ConvertRGB24ToY_SSE2(const uint8_t* rgb, uint8_t* y, int width) { const int max_width = width & ~31; int i; for (i = 0; i < max_width; rgb += 3 * 16 * 2) { __m128i rgb_plane[6]; int j; - RGB24PackedToPlanar(rgb, rgb_plane); + RGB24PackedToPlanar_SSE2(rgb, rgb_plane); for (j = 0; j < 2; ++j, i += 16) { const __m128i zero = _mm_setzero_si128(); @@ -566,13 +576,13 @@ static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) { r = _mm_unpacklo_epi8(rgb_plane[0 + j], zero); g = _mm_unpacklo_epi8(rgb_plane[2 + j], zero); b = _mm_unpacklo_epi8(rgb_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y0); + ConvertRGBToY_SSE2(&r, &g, &b, &Y0); // Convert to 16-bit Y. r = _mm_unpackhi_epi8(rgb_plane[0 + j], zero); g = _mm_unpackhi_epi8(rgb_plane[2 + j], zero); b = _mm_unpackhi_epi8(rgb_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y1); + ConvertRGBToY_SSE2(&r, &g, &b, &Y1); // Cast to 8-bit and store. STORE_16(_mm_packus_epi16(Y0, Y1), y + i); @@ -583,14 +593,14 @@ static void ConvertRGB24ToY(const uint8_t* rgb, uint8_t* y, int width) { } } -static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) { +static void ConvertBGR24ToY_SSE2(const uint8_t* bgr, uint8_t* y, int width) { const int max_width = width & ~31; int i; for (i = 0; i < max_width; bgr += 3 * 16 * 2) { __m128i bgr_plane[6]; int j; - RGB24PackedToPlanar(bgr, bgr_plane); + RGB24PackedToPlanar_SSE2(bgr, bgr_plane); for (j = 0; j < 2; ++j, i += 16) { const __m128i zero = _mm_setzero_si128(); @@ -600,13 +610,13 @@ static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) { b = _mm_unpacklo_epi8(bgr_plane[0 + j], zero); g = _mm_unpacklo_epi8(bgr_plane[2 + j], zero); r = _mm_unpacklo_epi8(bgr_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y0); + ConvertRGBToY_SSE2(&r, &g, &b, &Y0); // Convert to 16-bit Y. b = _mm_unpackhi_epi8(bgr_plane[0 + j], zero); g = _mm_unpackhi_epi8(bgr_plane[2 + j], zero); r = _mm_unpackhi_epi8(bgr_plane[4 + j], zero); - ConvertRGBToY(&r, &g, &b, &Y1); + ConvertRGBToY_SSE2(&r, &g, &b, &Y1); // Cast to 8-bit and store. STORE_16(_mm_packus_epi16(Y0, Y1), y + i); @@ -617,14 +627,14 @@ static void ConvertBGR24ToY(const uint8_t* bgr, uint8_t* y, int width) { } } -static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) { +static void ConvertARGBToY_SSE2(const uint32_t* argb, uint8_t* y, int width) { const int max_width = width & ~15; int i; for (i = 0; i < max_width; i += 16) { __m128i Y0, Y1, rgb[6]; - RGB32PackedToPlanar(&argb[i], rgb); - ConvertRGBToY(&rgb[0], &rgb[2], &rgb[4], &Y0); - ConvertRGBToY(&rgb[1], &rgb[3], &rgb[5], &Y1); + RGB32PackedToPlanar_SSE2(&argb[i], rgb); + ConvertRGBToY_SSE2(&rgb[0], &rgb[2], &rgb[4], &Y0); + ConvertRGBToY_SSE2(&rgb[1], &rgb[3], &rgb[5], &Y1); STORE_16(_mm_packus_epi16(Y0, Y1), y + i); } for (; i < width; ++i) { // left-over @@ -636,31 +646,33 @@ static void ConvertARGBToY(const uint32_t* argb, uint8_t* y, int width) { // Horizontal add (doubled) of two 16b values, result is 16b. // in: A | B | C | D | ... -> out: 2*(A+B) | 2*(C+D) | ... -static void HorizontalAddPack(const __m128i* const A, const __m128i* const B, - __m128i* const out) { +static void HorizontalAddPack_SSE2(const __m128i* const A, + const __m128i* const B, + __m128i* const out) { const __m128i k2 = _mm_set1_epi16(2); const __m128i C = _mm_madd_epi16(*A, k2); const __m128i D = _mm_madd_epi16(*B, k2); *out = _mm_packs_epi32(C, D); } -static void ConvertARGBToUV(const uint32_t* argb, uint8_t* u, uint8_t* v, - int src_width, int do_store) { +static void ConvertARGBToUV_SSE2(const uint32_t* argb, + uint8_t* u, uint8_t* v, + int src_width, int do_store) { const int max_width = src_width & ~31; int i; for (i = 0; i < max_width; i += 32, u += 16, v += 16) { __m128i rgb[6], U0, V0, U1, V1; - RGB32PackedToPlanar(&argb[i], rgb); - HorizontalAddPack(&rgb[0], &rgb[1], &rgb[0]); - HorizontalAddPack(&rgb[2], &rgb[3], &rgb[2]); - HorizontalAddPack(&rgb[4], &rgb[5], &rgb[4]); - ConvertRGBToUV(&rgb[0], &rgb[2], &rgb[4], &U0, &V0); + RGB32PackedToPlanar_SSE2(&argb[i], rgb); + HorizontalAddPack_SSE2(&rgb[0], &rgb[1], &rgb[0]); + HorizontalAddPack_SSE2(&rgb[2], &rgb[3], &rgb[2]); + HorizontalAddPack_SSE2(&rgb[4], &rgb[5], &rgb[4]); + ConvertRGBToUV_SSE2(&rgb[0], &rgb[2], &rgb[4], &U0, &V0); - RGB32PackedToPlanar(&argb[i + 16], rgb); - HorizontalAddPack(&rgb[0], &rgb[1], &rgb[0]); - HorizontalAddPack(&rgb[2], &rgb[3], &rgb[2]); - HorizontalAddPack(&rgb[4], &rgb[5], &rgb[4]); - ConvertRGBToUV(&rgb[0], &rgb[2], &rgb[4], &U1, &V1); + RGB32PackedToPlanar_SSE2(&argb[i + 16], rgb); + HorizontalAddPack_SSE2(&rgb[0], &rgb[1], &rgb[0]); + HorizontalAddPack_SSE2(&rgb[2], &rgb[3], &rgb[2]); + HorizontalAddPack_SSE2(&rgb[4], &rgb[5], &rgb[4]); + ConvertRGBToUV_SSE2(&rgb[0], &rgb[2], &rgb[4], &U1, &V1); U0 = _mm_packus_epi16(U0, U1); V0 = _mm_packus_epi16(V0, V1); @@ -679,10 +691,9 @@ static void ConvertARGBToUV(const uint32_t* argb, uint8_t* u, uint8_t* v, } // Convert 16 packed ARGB 16b-values to r[], g[], b[] -static WEBP_INLINE void RGBA32PackedToPlanar_16b(const uint16_t* const rgbx, - __m128i* const r, - __m128i* const g, - __m128i* const b) { +static WEBP_INLINE void RGBA32PackedToPlanar_16b_SSE2( + const uint16_t* const rgbx, + __m128i* const r, __m128i* const g, __m128i* const b) { const __m128i in0 = LOAD_16(rgbx + 0); // r0 | g0 | b0 |x| r1 | g1 | b1 |x const __m128i in1 = LOAD_16(rgbx + 8); // r2 | g2 | b2 |x| r3 | g3 | b3 |x const __m128i in2 = LOAD_16(rgbx + 16); // r4 | ... @@ -701,16 +712,16 @@ static WEBP_INLINE void RGBA32PackedToPlanar_16b(const uint16_t* const rgbx, *b = _mm_unpacklo_epi64(B1, B3); } -static void ConvertRGBA32ToUV(const uint16_t* rgb, - uint8_t* u, uint8_t* v, int width) { +static void ConvertRGBA32ToUV_SSE2(const uint16_t* rgb, + uint8_t* u, uint8_t* v, int width) { const int max_width = width & ~15; const uint16_t* const last_rgb = rgb + 4 * max_width; while (rgb < last_rgb) { __m128i r, g, b, U0, V0, U1, V1; - RGBA32PackedToPlanar_16b(rgb + 0, &r, &g, &b); - ConvertRGBToUV(&r, &g, &b, &U0, &V0); - RGBA32PackedToPlanar_16b(rgb + 32, &r, &g, &b); - ConvertRGBToUV(&r, &g, &b, &U1, &V1); + RGBA32PackedToPlanar_16b_SSE2(rgb + 0, &r, &g, &b); + ConvertRGBToUV_SSE2(&r, &g, &b, &U0, &V0); + RGBA32PackedToPlanar_16b_SSE2(rgb + 32, &r, &g, &b); + ConvertRGBToUV_SSE2(&r, &g, &b, &U1, &V1); STORE_16(_mm_packus_epi16(U0, U1), u); STORE_16(_mm_packus_epi16(V0, V1), v); u += 16; @@ -727,13 +738,13 @@ static void ConvertRGBA32ToUV(const uint16_t* rgb, extern void WebPInitConvertARGBToYUVSSE2(void); WEBP_TSAN_IGNORE_FUNCTION void WebPInitConvertARGBToYUVSSE2(void) { - WebPConvertARGBToY = ConvertARGBToY; - WebPConvertARGBToUV = ConvertARGBToUV; + WebPConvertARGBToY = ConvertARGBToY_SSE2; + WebPConvertARGBToUV = ConvertARGBToUV_SSE2; - WebPConvertRGB24ToY = ConvertRGB24ToY; - WebPConvertBGR24ToY = ConvertBGR24ToY; + WebPConvertRGB24ToY = ConvertRGB24ToY_SSE2; + WebPConvertBGR24ToY = ConvertBGR24ToY_SSE2; - WebPConvertRGBA32ToUV = ConvertRGBA32ToUV; + WebPConvertRGBA32ToUV = ConvertRGBA32ToUV_SSE2; } //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/enc/alpha_enc.c b/3rdparty/libwebp/src/enc/alpha_enc.c similarity index 95% rename from 3rdparty/libwebp/enc/alpha_enc.c rename to 3rdparty/libwebp/src/enc/alpha_enc.c index 5a2c931f92..7e8d87f22e 100644 --- a/3rdparty/libwebp/enc/alpha_enc.c +++ b/3rdparty/libwebp/src/enc/alpha_enc.c @@ -14,12 +14,12 @@ #include #include -#include "./vp8i_enc.h" -#include "../dsp/dsp.h" -#include "../utils/filters_utils.h" -#include "../utils/quant_levels_utils.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" +#include "src/enc/vp8i_enc.h" +#include "src/dsp/dsp.h" +#include "src/utils/filters_utils.h" +#include "src/utils/quant_levels_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" // ----------------------------------------------------------------------------- // Encodes the given alpha data via specified compression method 'method'. @@ -44,11 +44,11 @@ // invalid quality or method, or // memory allocation for the compressed data fails. -#include "../enc/vp8li_enc.h" +#include "src/enc/vp8li_enc.h" static int EncodeLossless(const uint8_t* const data, int width, int height, int effort_level, // in [0..6] range - VP8LBitWriter* const bw, + int use_quality_100, VP8LBitWriter* const bw, WebPAuxStats* const stats) { int ok = 0; WebPConfig config; @@ -76,7 +76,10 @@ static int EncodeLossless(const uint8_t* const data, int width, int height, // Set a low default quality for encoding alpha. Ensure that Alpha quality at // lower methods (3 and below) is less than the threshold for triggering // costly 'BackwardReferencesTraceBackwards'. - config.quality = 8.f * effort_level; + // If the alpha quality is set to 100 and the method to 6, allow for a high + // lossless quality to trigger the cruncher. + config.quality = + (use_quality_100 && effort_level == 6) ? 100 : 8.f * effort_level; assert(config.quality >= 0 && config.quality <= 100.f); // TODO(urvang): Temporary fix to avoid generating images that trigger @@ -134,7 +137,7 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height, if (method != ALPHA_NO_COMPRESSION) { ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3); ok = ok && EncodeLossless(alpha_src, width, height, effort_level, - &tmp_bw, &result->stats); + !reduce_levels, &tmp_bw, &result->stats); if (ok) { output = VP8LBitWriterFinish(&tmp_bw); output_size = VP8LBitWriterNumBytes(&tmp_bw); @@ -264,6 +267,7 @@ static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height, reduce_levels, effort_level, NULL, &best); } if (ok) { +#if !defined(WEBP_DISABLE_STATS) if (stats != NULL) { stats->lossless_features = best.stats.lossless_features; stats->histogram_bits = best.stats.histogram_bits; @@ -274,6 +278,9 @@ static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height, stats->lossless_hdr_size = best.stats.lossless_hdr_size; stats->lossless_data_size = best.stats.lossless_data_size; } +#else + (void)stats; +#endif *output_size = VP8BitWriterSize(&best.bw); *output = VP8BitWriterBuf(&best.bw); } else { @@ -339,10 +346,12 @@ static int EncodeAlpha(VP8Encoder* const enc, ok = ApplyFiltersAndEncode(quant_alpha, width, height, data_size, method, filter, reduce_levels, effort_level, output, output_size, pic->stats); +#if !defined(WEBP_DISABLE_STATS) if (pic->stats != NULL) { // need stats? pic->stats->coded_size += (int)(*output_size); enc->sse_[3] = sse; } +#endif } WebPSafeFree(quant_alpha); diff --git a/3rdparty/libwebp/enc/analysis_enc.c b/3rdparty/libwebp/src/enc/analysis_enc.c similarity index 99% rename from 3rdparty/libwebp/enc/analysis_enc.c rename to 3rdparty/libwebp/src/enc/analysis_enc.c index dce159b316..08f471f5f8 100644 --- a/3rdparty/libwebp/enc/analysis_enc.c +++ b/3rdparty/libwebp/src/enc/analysis_enc.c @@ -15,9 +15,9 @@ #include #include -#include "./vp8i_enc.h" -#include "./cost_enc.h" -#include "../utils/utils.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/cost_enc.h" +#include "src/utils/utils.h" #define MAX_ITERS_K_MEANS 6 diff --git a/3rdparty/libwebp/src/enc/backward_references_cost_enc.c b/3rdparty/libwebp/src/enc/backward_references_cost_enc.c new file mode 100644 index 0000000000..7175496c7f --- /dev/null +++ b/3rdparty/libwebp/src/enc/backward_references_cost_enc.c @@ -0,0 +1,790 @@ +// Copyright 2017 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Improves a given set of backward references by analyzing its bit cost. +// The algorithm is similar to the Zopfli compression algorithm but tailored to +// images. +// +// Author: Vincent Rabaud (vrabaud@google.com) +// + +#include + +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/dsp/lossless_common.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" + +#define VALUES_IN_BYTE 256 + +extern void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs); +extern int VP8LDistanceToPlaneCode(int xsize, int dist); +extern void VP8LBackwardRefsCursorAdd(VP8LBackwardRefs* const refs, + const PixOrCopy v); + +typedef struct { + double alpha_[VALUES_IN_BYTE]; + double red_[VALUES_IN_BYTE]; + double blue_[VALUES_IN_BYTE]; + double distance_[NUM_DISTANCE_CODES]; + double* literal_; +} CostModel; + +static void ConvertPopulationCountTableToBitEstimates( + int num_symbols, const uint32_t population_counts[], double output[]) { + uint32_t sum = 0; + int nonzeros = 0; + int i; + for (i = 0; i < num_symbols; ++i) { + sum += population_counts[i]; + if (population_counts[i] > 0) { + ++nonzeros; + } + } + if (nonzeros <= 1) { + memset(output, 0, num_symbols * sizeof(*output)); + } else { + const double logsum = VP8LFastLog2(sum); + for (i = 0; i < num_symbols; ++i) { + output[i] = logsum - VP8LFastLog2(population_counts[i]); + } + } +} + +static int CostModelBuild(CostModel* const m, int xsize, int cache_bits, + const VP8LBackwardRefs* const refs) { + int ok = 0; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits); + if (histo == NULL) goto Error; + + // The following code is similar to VP8LHistogramCreate but converts the + // distance to plane code. + VP8LHistogramInit(histo, cache_bits); + while (VP8LRefsCursorOk(&c)) { + VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos, VP8LDistanceToPlaneCode, + xsize); + VP8LRefsCursorNext(&c); + } + + ConvertPopulationCountTableToBitEstimates( + VP8LHistogramNumCodes(histo->palette_code_bits_), + histo->literal_, m->literal_); + ConvertPopulationCountTableToBitEstimates( + VALUES_IN_BYTE, histo->red_, m->red_); + ConvertPopulationCountTableToBitEstimates( + VALUES_IN_BYTE, histo->blue_, m->blue_); + ConvertPopulationCountTableToBitEstimates( + VALUES_IN_BYTE, histo->alpha_, m->alpha_); + ConvertPopulationCountTableToBitEstimates( + NUM_DISTANCE_CODES, histo->distance_, m->distance_); + ok = 1; + + Error: + VP8LFreeHistogram(histo); + return ok; +} + +static WEBP_INLINE double GetLiteralCost(const CostModel* const m, uint32_t v) { + return m->alpha_[v >> 24] + + m->red_[(v >> 16) & 0xff] + + m->literal_[(v >> 8) & 0xff] + + m->blue_[v & 0xff]; +} + +static WEBP_INLINE double GetCacheCost(const CostModel* const m, uint32_t idx) { + const int literal_idx = VALUES_IN_BYTE + NUM_LENGTH_CODES + idx; + return m->literal_[literal_idx]; +} + +static WEBP_INLINE double GetLengthCost(const CostModel* const m, + uint32_t length) { + int code, extra_bits; + VP8LPrefixEncodeBits(length, &code, &extra_bits); + return m->literal_[VALUES_IN_BYTE + code] + extra_bits; +} + +static WEBP_INLINE double GetDistanceCost(const CostModel* const m, + uint32_t distance) { + int code, extra_bits; + VP8LPrefixEncodeBits(distance, &code, &extra_bits); + return m->distance_[code] + extra_bits; +} + +static WEBP_INLINE void AddSingleLiteralWithCostModel( + const uint32_t* const argb, VP8LColorCache* const hashers, + const CostModel* const cost_model, int idx, int use_color_cache, + float prev_cost, float* const cost, uint16_t* const dist_array) { + double cost_val = prev_cost; + const uint32_t color = argb[idx]; + const int ix = use_color_cache ? VP8LColorCacheContains(hashers, color) : -1; + if (ix >= 0) { + // use_color_cache is true and hashers contains color + const double mul0 = 0.68; + cost_val += GetCacheCost(cost_model, ix) * mul0; + } else { + const double mul1 = 0.82; + if (use_color_cache) VP8LColorCacheInsert(hashers, color); + cost_val += GetLiteralCost(cost_model, color) * mul1; + } + if (cost[idx] > cost_val) { + cost[idx] = (float)cost_val; + dist_array[idx] = 1; // only one is inserted. + } +} + +// ----------------------------------------------------------------------------- +// CostManager and interval handling + +// Empirical value to avoid high memory consumption but good for performance. +#define COST_CACHE_INTERVAL_SIZE_MAX 500 + +// To perform backward reference every pixel at index index_ is considered and +// the cost for the MAX_LENGTH following pixels computed. Those following pixels +// at index index_ + k (k from 0 to MAX_LENGTH) have a cost of: +// cost_ = distance cost at index + GetLengthCost(cost_model, k) +// and the minimum value is kept. GetLengthCost(cost_model, k) is cached in an +// array of size MAX_LENGTH. +// Instead of performing MAX_LENGTH comparisons per pixel, we keep track of the +// minimal values using intervals of constant cost. +// An interval is defined by the index_ of the pixel that generated it and +// is only useful in a range of indices from start_ to end_ (exclusive), i.e. +// it contains the minimum value for pixels between start_ and end_. +// Intervals are stored in a linked list and ordered by start_. When a new +// interval has a better value, old intervals are split or removed. There are +// therefore no overlapping intervals. +typedef struct CostInterval CostInterval; +struct CostInterval { + float cost_; + int start_; + int end_; + int index_; + CostInterval* previous_; + CostInterval* next_; +}; + +// The GetLengthCost(cost_model, k) are cached in a CostCacheInterval. +typedef struct { + double cost_; + int start_; + int end_; // Exclusive. +} CostCacheInterval; + +// This structure is in charge of managing intervals and costs. +// It caches the different CostCacheInterval, caches the different +// GetLengthCost(cost_model, k) in cost_cache_ and the CostInterval's (whose +// count_ is limited by COST_CACHE_INTERVAL_SIZE_MAX). +#define COST_MANAGER_MAX_FREE_LIST 10 +typedef struct { + CostInterval* head_; + int count_; // The number of stored intervals. + CostCacheInterval* cache_intervals_; + size_t cache_intervals_size_; + double cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k). + float* costs_; + uint16_t* dist_array_; + // Most of the time, we only need few intervals -> use a free-list, to avoid + // fragmentation with small allocs in most common cases. + CostInterval intervals_[COST_MANAGER_MAX_FREE_LIST]; + CostInterval* free_intervals_; + // These are regularly malloc'd remains. This list can't grow larger than than + // size COST_CACHE_INTERVAL_SIZE_MAX - COST_MANAGER_MAX_FREE_LIST, note. + CostInterval* recycled_intervals_; +} CostManager; + +static void CostIntervalAddToFreeList(CostManager* const manager, + CostInterval* const interval) { + interval->next_ = manager->free_intervals_; + manager->free_intervals_ = interval; +} + +static int CostIntervalIsInFreeList(const CostManager* const manager, + const CostInterval* const interval) { + return (interval >= &manager->intervals_[0] && + interval <= &manager->intervals_[COST_MANAGER_MAX_FREE_LIST - 1]); +} + +static void CostManagerInitFreeList(CostManager* const manager) { + int i; + manager->free_intervals_ = NULL; + for (i = 0; i < COST_MANAGER_MAX_FREE_LIST; ++i) { + CostIntervalAddToFreeList(manager, &manager->intervals_[i]); + } +} + +static void DeleteIntervalList(CostManager* const manager, + const CostInterval* interval) { + while (interval != NULL) { + const CostInterval* const next = interval->next_; + if (!CostIntervalIsInFreeList(manager, interval)) { + WebPSafeFree((void*)interval); + } // else: do nothing + interval = next; + } +} + +static void CostManagerClear(CostManager* const manager) { + if (manager == NULL) return; + + WebPSafeFree(manager->costs_); + WebPSafeFree(manager->cache_intervals_); + + // Clear the interval lists. + DeleteIntervalList(manager, manager->head_); + manager->head_ = NULL; + DeleteIntervalList(manager, manager->recycled_intervals_); + manager->recycled_intervals_ = NULL; + + // Reset pointers, count_ and cache_intervals_size_. + memset(manager, 0, sizeof(*manager)); + CostManagerInitFreeList(manager); +} + +static int CostManagerInit(CostManager* const manager, + uint16_t* const dist_array, int pix_count, + const CostModel* const cost_model) { + int i; + const int cost_cache_size = (pix_count > MAX_LENGTH) ? MAX_LENGTH : pix_count; + + manager->costs_ = NULL; + manager->cache_intervals_ = NULL; + manager->head_ = NULL; + manager->recycled_intervals_ = NULL; + manager->count_ = 0; + manager->dist_array_ = dist_array; + CostManagerInitFreeList(manager); + + // Fill in the cost_cache_. + manager->cache_intervals_size_ = 1; + manager->cost_cache_[0] = GetLengthCost(cost_model, 0); + for (i = 1; i < cost_cache_size; ++i) { + manager->cost_cache_[i] = GetLengthCost(cost_model, i); + // Get the number of bound intervals. + if (manager->cost_cache_[i] != manager->cost_cache_[i - 1]) { + ++manager->cache_intervals_size_; + } + } + + // With the current cost model, we usually have below 20 intervals. + // The worst case scenario with a cost model would be if every length has a + // different cost, hence MAX_LENGTH but that is impossible with the current + // implementation that spirals around a pixel. + assert(manager->cache_intervals_size_ <= MAX_LENGTH); + manager->cache_intervals_ = (CostCacheInterval*)WebPSafeMalloc( + manager->cache_intervals_size_, sizeof(*manager->cache_intervals_)); + if (manager->cache_intervals_ == NULL) { + CostManagerClear(manager); + return 0; + } + + // Fill in the cache_intervals_. + { + CostCacheInterval* cur = manager->cache_intervals_; + + // Consecutive values in cost_cache_ are compared and if a big enough + // difference is found, a new interval is created and bounded. + cur->start_ = 0; + cur->end_ = 1; + cur->cost_ = manager->cost_cache_[0]; + for (i = 1; i < cost_cache_size; ++i) { + const double cost_val = manager->cost_cache_[i]; + if (cost_val != cur->cost_) { + ++cur; + // Initialize an interval. + cur->start_ = i; + cur->cost_ = cost_val; + } + cur->end_ = i + 1; + } + } + + manager->costs_ = (float*)WebPSafeMalloc(pix_count, sizeof(*manager->costs_)); + if (manager->costs_ == NULL) { + CostManagerClear(manager); + return 0; + } + // Set the initial costs_ high for every pixel as we will keep the minimum. + for (i = 0; i < pix_count; ++i) manager->costs_[i] = 1e38f; + + return 1; +} + +// Given the cost and the position that define an interval, update the cost at +// pixel 'i' if it is smaller than the previously computed value. +static WEBP_INLINE void UpdateCost(CostManager* const manager, int i, + int position, float cost) { + const int k = i - position; + assert(k >= 0 && k < MAX_LENGTH); + + if (manager->costs_[i] > cost) { + manager->costs_[i] = cost; + manager->dist_array_[i] = k + 1; + } +} + +// Given the cost and the position that define an interval, update the cost for +// all the pixels between 'start' and 'end' excluded. +static WEBP_INLINE void UpdateCostPerInterval(CostManager* const manager, + int start, int end, int position, + float cost) { + int i; + for (i = start; i < end; ++i) UpdateCost(manager, i, position, cost); +} + +// Given two intervals, make 'prev' be the previous one of 'next' in 'manager'. +static WEBP_INLINE void ConnectIntervals(CostManager* const manager, + CostInterval* const prev, + CostInterval* const next) { + if (prev != NULL) { + prev->next_ = next; + } else { + manager->head_ = next; + } + + if (next != NULL) next->previous_ = prev; +} + +// Pop an interval in the manager. +static WEBP_INLINE void PopInterval(CostManager* const manager, + CostInterval* const interval) { + if (interval == NULL) return; + + ConnectIntervals(manager, interval->previous_, interval->next_); + if (CostIntervalIsInFreeList(manager, interval)) { + CostIntervalAddToFreeList(manager, interval); + } else { // recycle regularly malloc'd intervals too + interval->next_ = manager->recycled_intervals_; + manager->recycled_intervals_ = interval; + } + --manager->count_; + assert(manager->count_ >= 0); +} + +// Update the cost at index i by going over all the stored intervals that +// overlap with i. +// If 'do_clean_intervals' is set to something different than 0, intervals that +// end before 'i' will be popped. +static WEBP_INLINE void UpdateCostAtIndex(CostManager* const manager, int i, + int do_clean_intervals) { + CostInterval* current = manager->head_; + + while (current != NULL && current->start_ <= i) { + CostInterval* const next = current->next_; + if (current->end_ <= i) { + if (do_clean_intervals) { + // We have an outdated interval, remove it. + PopInterval(manager, current); + } + } else { + UpdateCost(manager, i, current->index_, current->cost_); + } + current = next; + } +} + +// Given a current orphan interval and its previous interval, before +// it was orphaned (which can be NULL), set it at the right place in the list +// of intervals using the start_ ordering and the previous interval as a hint. +static WEBP_INLINE void PositionOrphanInterval(CostManager* const manager, + CostInterval* const current, + CostInterval* previous) { + assert(current != NULL); + + if (previous == NULL) previous = manager->head_; + while (previous != NULL && current->start_ < previous->start_) { + previous = previous->previous_; + } + while (previous != NULL && previous->next_ != NULL && + previous->next_->start_ < current->start_) { + previous = previous->next_; + } + + if (previous != NULL) { + ConnectIntervals(manager, current, previous->next_); + } else { + ConnectIntervals(manager, current, manager->head_); + } + ConnectIntervals(manager, previous, current); +} + +// Insert an interval in the list contained in the manager by starting at +// interval_in as a hint. The intervals are sorted by start_ value. +static WEBP_INLINE void InsertInterval(CostManager* const manager, + CostInterval* const interval_in, + float cost, int position, int start, + int end) { + CostInterval* interval_new; + + if (start >= end) return; + if (manager->count_ >= COST_CACHE_INTERVAL_SIZE_MAX) { + // Serialize the interval if we cannot store it. + UpdateCostPerInterval(manager, start, end, position, cost); + return; + } + if (manager->free_intervals_ != NULL) { + interval_new = manager->free_intervals_; + manager->free_intervals_ = interval_new->next_; + } else if (manager->recycled_intervals_ != NULL) { + interval_new = manager->recycled_intervals_; + manager->recycled_intervals_ = interval_new->next_; + } else { // malloc for good + interval_new = (CostInterval*)WebPSafeMalloc(1, sizeof(*interval_new)); + if (interval_new == NULL) { + // Write down the interval if we cannot create it. + UpdateCostPerInterval(manager, start, end, position, cost); + return; + } + } + + interval_new->cost_ = cost; + interval_new->index_ = position; + interval_new->start_ = start; + interval_new->end_ = end; + PositionOrphanInterval(manager, interval_new, interval_in); + + ++manager->count_; +} + +// Given a new cost interval defined by its start at position, its length value +// and distance_cost, add its contributions to the previous intervals and costs. +// If handling the interval or one of its subintervals becomes to heavy, its +// contribution is added to the costs right away. +static WEBP_INLINE void PushInterval(CostManager* const manager, + double distance_cost, int position, + int len) { + size_t i; + CostInterval* interval = manager->head_; + CostInterval* interval_next; + const CostCacheInterval* const cost_cache_intervals = + manager->cache_intervals_; + // If the interval is small enough, no need to deal with the heavy + // interval logic, just serialize it right away. This constant is empirical. + const int kSkipDistance = 10; + + if (len < kSkipDistance) { + int j; + for (j = position; j < position + len; ++j) { + const int k = j - position; + float cost_tmp; + assert(k >= 0 && k < MAX_LENGTH); + cost_tmp = (float)(distance_cost + manager->cost_cache_[k]); + + if (manager->costs_[j] > cost_tmp) { + manager->costs_[j] = cost_tmp; + manager->dist_array_[j] = k + 1; + } + } + return; + } + + for (i = 0; i < manager->cache_intervals_size_ && + cost_cache_intervals[i].start_ < len; + ++i) { + // Define the intersection of the ith interval with the new one. + int start = position + cost_cache_intervals[i].start_; + const int end = position + (cost_cache_intervals[i].end_ > len + ? len + : cost_cache_intervals[i].end_); + const float cost = (float)(distance_cost + cost_cache_intervals[i].cost_); + + for (; interval != NULL && interval->start_ < end; + interval = interval_next) { + interval_next = interval->next_; + + // Make sure we have some overlap + if (start >= interval->end_) continue; + + if (cost >= interval->cost_) { + // When intervals are represented, the lower, the better. + // [**********************************************************[ + // start end + // [----------------------------------[ + // interval->start_ interval->end_ + // If we are worse than what we already have, add whatever we have so + // far up to interval. + const int start_new = interval->end_; + InsertInterval(manager, interval, cost, position, start, + interval->start_); + start = start_new; + if (start >= end) break; + continue; + } + + if (start <= interval->start_) { + if (interval->end_ <= end) { + // [----------------------------------[ + // interval->start_ interval->end_ + // [**************************************************************[ + // start end + // We can safely remove the old interval as it is fully included. + PopInterval(manager, interval); + } else { + // [------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + interval->start_ = end; + break; + } + } else { + if (end < interval->end_) { + // [--------------------------------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + // We have to split the old interval as it fully contains the new one. + const int end_original = interval->end_; + interval->end_ = start; + InsertInterval(manager, interval, interval->cost_, interval->index_, + end, end_original); + interval = interval->next_; + break; + } else { + // [------------------------------------[ + // interval->start_ interval->end_ + // [*****************************[ + // start end + interval->end_ = start; + } + } + } + // Insert the remaining interval from start to end. + InsertInterval(manager, interval, cost, position, start, end); + } +} + +static int BackwardReferencesHashChainDistanceOnly( + int xsize, int ysize, const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, const VP8LBackwardRefs* const refs, + uint16_t* const dist_array) { + int i; + int ok = 0; + int cc_init = 0; + const int pix_count = xsize * ysize; + const int use_color_cache = (cache_bits > 0); + const size_t literal_array_size = + sizeof(double) * (NUM_LITERAL_CODES + NUM_LENGTH_CODES + + ((cache_bits > 0) ? (1 << cache_bits) : 0)); + const size_t cost_model_size = sizeof(CostModel) + literal_array_size; + CostModel* const cost_model = + (CostModel*)WebPSafeCalloc(1ULL, cost_model_size); + VP8LColorCache hashers; + CostManager* cost_manager = + (CostManager*)WebPSafeMalloc(1ULL, sizeof(*cost_manager)); + int offset_prev = -1, len_prev = -1; + double offset_cost = -1; + int first_offset_is_constant = -1; // initialized with 'impossible' value + int reach = 0; + + if (cost_model == NULL || cost_manager == NULL) goto Error; + + cost_model->literal_ = (double*)(cost_model + 1); + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + + if (!CostModelBuild(cost_model, xsize, cache_bits, refs)) { + goto Error; + } + + if (!CostManagerInit(cost_manager, dist_array, pix_count, cost_model)) { + goto Error; + } + + // We loop one pixel at a time, but store all currently best points to + // non-processed locations from this point. + dist_array[0] = 0; + // Add first pixel as literal. + AddSingleLiteralWithCostModel(argb, &hashers, cost_model, 0, use_color_cache, + 0.f, cost_manager->costs_, dist_array); + + for (i = 1; i < pix_count; ++i) { + const float prev_cost = cost_manager->costs_[i - 1]; + int offset, len; + VP8LHashChainFindCopy(hash_chain, i, &offset, &len); + + // Try adding the pixel as a literal. + AddSingleLiteralWithCostModel(argb, &hashers, cost_model, i, + use_color_cache, prev_cost, + cost_manager->costs_, dist_array); + + // If we are dealing with a non-literal. + if (len >= 2) { + if (offset != offset_prev) { + const int code = VP8LDistanceToPlaneCode(xsize, offset); + offset_cost = GetDistanceCost(cost_model, code); + first_offset_is_constant = 1; + PushInterval(cost_manager, prev_cost + offset_cost, i, len); + } else { + assert(offset_cost >= 0); + assert(len_prev >= 0); + assert(first_offset_is_constant == 0 || first_offset_is_constant == 1); + // Instead of considering all contributions from a pixel i by calling: + // PushInterval(cost_manager, prev_cost + offset_cost, i, len); + // we optimize these contributions in case offset_cost stays the same + // for consecutive pixels. This describes a set of pixels similar to a + // previous set (e.g. constant color regions). + if (first_offset_is_constant) { + reach = i - 1 + len_prev - 1; + first_offset_is_constant = 0; + } + + if (i + len - 1 > reach) { + // We can only be go further with the same offset if the previous + // length was maxed, hence len_prev == len == MAX_LENGTH. + // TODO(vrabaud), bump i to the end right away (insert cache and + // update cost). + // TODO(vrabaud), check if one of the points in between does not have + // a lower cost. + // Already consider the pixel at "reach" to add intervals that are + // better than whatever we add. + int offset_j, len_j = 0; + int j; + assert(len == MAX_LENGTH || len == pix_count - i); + // Figure out the last consecutive pixel within [i, reach + 1] with + // the same offset. + for (j = i; j <= reach; ++j) { + VP8LHashChainFindCopy(hash_chain, j + 1, &offset_j, &len_j); + if (offset_j != offset) { + VP8LHashChainFindCopy(hash_chain, j, &offset_j, &len_j); + break; + } + } + // Update the cost at j - 1 and j. + UpdateCostAtIndex(cost_manager, j - 1, 0); + UpdateCostAtIndex(cost_manager, j, 0); + + PushInterval(cost_manager, cost_manager->costs_[j - 1] + offset_cost, + j, len_j); + reach = j + len_j - 1; + } + } + } + + UpdateCostAtIndex(cost_manager, i, 1); + offset_prev = offset; + len_prev = len; + } + + ok = !refs->error_; +Error: + if (cc_init) VP8LColorCacheClear(&hashers); + CostManagerClear(cost_manager); + WebPSafeFree(cost_model); + WebPSafeFree(cost_manager); + return ok; +} + +// We pack the path at the end of *dist_array and return +// a pointer to this part of the array. Example: +// dist_array = [1x2xx3x2] => packed [1x2x1232], chosen_path = [1232] +static void TraceBackwards(uint16_t* const dist_array, + int dist_array_size, + uint16_t** const chosen_path, + int* const chosen_path_size) { + uint16_t* path = dist_array + dist_array_size; + uint16_t* cur = dist_array + dist_array_size - 1; + while (cur >= dist_array) { + const int k = *cur; + --path; + *path = k; + cur -= k; + } + *chosen_path = path; + *chosen_path_size = (int)(dist_array + dist_array_size - path); +} + +static int BackwardReferencesHashChainFollowChosenPath( + const uint32_t* const argb, int cache_bits, + const uint16_t* const chosen_path, int chosen_path_size, + const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs) { + const int use_color_cache = (cache_bits > 0); + int ix; + int i = 0; + int ok = 0; + int cc_init = 0; + VP8LColorCache hashers; + + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + + VP8LClearBackwardRefs(refs); + for (ix = 0; ix < chosen_path_size; ++ix) { + const int len = chosen_path[ix]; + if (len != 1) { + int k; + const int offset = VP8LHashChainFindOffset(hash_chain, i); + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); + if (use_color_cache) { + for (k = 0; k < len; ++k) { + VP8LColorCacheInsert(&hashers, argb[i + k]); + } + } + i += len; + } else { + PixOrCopy v; + const int idx = + use_color_cache ? VP8LColorCacheContains(&hashers, argb[i]) : -1; + if (idx >= 0) { + // use_color_cache is true and hashers contains argb[i] + // push pixel as a color cache index + v = PixOrCopyCreateCacheIdx(idx); + } else { + if (use_color_cache) VP8LColorCacheInsert(&hashers, argb[i]); + v = PixOrCopyCreateLiteral(argb[i]); + } + VP8LBackwardRefsCursorAdd(refs, v); + ++i; + } + } + ok = !refs->error_; + Error: + if (cc_init) VP8LColorCacheClear(&hashers); + return ok; +} + +// Returns 1 on success. +extern int VP8LBackwardReferencesTraceBackwards( + int xsize, int ysize, const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, + const VP8LBackwardRefs* const refs_src, VP8LBackwardRefs* const refs_dst); +int VP8LBackwardReferencesTraceBackwards(int xsize, int ysize, + const uint32_t* const argb, + int cache_bits, + const VP8LHashChain* const hash_chain, + const VP8LBackwardRefs* const refs_src, + VP8LBackwardRefs* const refs_dst) { + int ok = 0; + const int dist_array_size = xsize * ysize; + uint16_t* chosen_path = NULL; + int chosen_path_size = 0; + uint16_t* dist_array = + (uint16_t*)WebPSafeMalloc(dist_array_size, sizeof(*dist_array)); + + if (dist_array == NULL) goto Error; + + if (!BackwardReferencesHashChainDistanceOnly( + xsize, ysize, argb, cache_bits, hash_chain, refs_src, dist_array)) { + goto Error; + } + TraceBackwards(dist_array, dist_array_size, &chosen_path, &chosen_path_size); + if (!BackwardReferencesHashChainFollowChosenPath( + argb, cache_bits, chosen_path, chosen_path_size, hash_chain, + refs_dst)) { + goto Error; + } + ok = 1; + Error: + WebPSafeFree(dist_array); + return ok; +} diff --git a/3rdparty/libwebp/src/enc/backward_references_enc.c b/3rdparty/libwebp/src/enc/backward_references_enc.c new file mode 100644 index 0000000000..39230188b9 --- /dev/null +++ b/3rdparty/libwebp/src/enc/backward_references_enc.c @@ -0,0 +1,943 @@ +// Copyright 2012 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// +// Author: Jyrki Alakuijala (jyrki@google.com) +// + +#include +#include + +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/dsp/dsp.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" + +#define MIN_BLOCK_SIZE 256 // minimum block size for backward references + +#define MAX_ENTROPY (1e30f) + +// 1M window (4M bytes) minus 120 special codes for short distances. +#define WINDOW_SIZE ((1 << WINDOW_SIZE_BITS) - 120) + +// Minimum number of pixels for which it is cheaper to encode a +// distance + length instead of each pixel as a literal. +#define MIN_LENGTH 4 + +// ----------------------------------------------------------------------------- + +static const uint8_t plane_to_code_lut[128] = { + 96, 73, 55, 39, 23, 13, 5, 1, 255, 255, 255, 255, 255, 255, 255, 255, + 101, 78, 58, 42, 26, 16, 8, 2, 0, 3, 9, 17, 27, 43, 59, 79, + 102, 86, 62, 46, 32, 20, 10, 6, 4, 7, 11, 21, 33, 47, 63, 87, + 105, 90, 70, 52, 37, 28, 18, 14, 12, 15, 19, 29, 38, 53, 71, 91, + 110, 99, 82, 66, 48, 35, 30, 24, 22, 25, 31, 36, 49, 67, 83, 100, + 115, 108, 94, 76, 64, 50, 44, 40, 34, 41, 45, 51, 65, 77, 95, 109, + 118, 113, 103, 92, 80, 68, 60, 56, 54, 57, 61, 69, 81, 93, 104, 114, + 119, 116, 111, 106, 97, 88, 84, 74, 72, 75, 85, 89, 98, 107, 112, 117 +}; + +extern int VP8LDistanceToPlaneCode(int xsize, int dist); +int VP8LDistanceToPlaneCode(int xsize, int dist) { + const int yoffset = dist / xsize; + const int xoffset = dist - yoffset * xsize; + if (xoffset <= 8 && yoffset < 8) { + return plane_to_code_lut[yoffset * 16 + 8 - xoffset] + 1; + } else if (xoffset > xsize - 8 && yoffset < 7) { + return plane_to_code_lut[(yoffset + 1) * 16 + 8 + (xsize - xoffset)] + 1; + } + return dist + 120; +} + +// Returns the exact index where array1 and array2 are different. For an index +// inferior or equal to best_len_match, the return value just has to be strictly +// inferior to best_len_match. The current behavior is to return 0 if this index +// is best_len_match, and the index itself otherwise. +// If no two elements are the same, it returns max_limit. +static WEBP_INLINE int FindMatchLength(const uint32_t* const array1, + const uint32_t* const array2, + int best_len_match, int max_limit) { + // Before 'expensive' linear match, check if the two arrays match at the + // current best length index. + if (array1[best_len_match] != array2[best_len_match]) return 0; + + return VP8LVectorMismatch(array1, array2, max_limit); +} + +// ----------------------------------------------------------------------------- +// VP8LBackwardRefs + +struct PixOrCopyBlock { + PixOrCopyBlock* next_; // next block (or NULL) + PixOrCopy* start_; // data start + int size_; // currently used size +}; + +extern void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs); +void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs) { + assert(refs != NULL); + if (refs->tail_ != NULL) { + *refs->tail_ = refs->free_blocks_; // recycle all blocks at once + } + refs->free_blocks_ = refs->refs_; + refs->tail_ = &refs->refs_; + refs->last_block_ = NULL; + refs->refs_ = NULL; +} + +void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs) { + assert(refs != NULL); + VP8LClearBackwardRefs(refs); + while (refs->free_blocks_ != NULL) { + PixOrCopyBlock* const next = refs->free_blocks_->next_; + WebPSafeFree(refs->free_blocks_); + refs->free_blocks_ = next; + } +} + +void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size) { + assert(refs != NULL); + memset(refs, 0, sizeof(*refs)); + refs->tail_ = &refs->refs_; + refs->block_size_ = + (block_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : block_size; +} + +VP8LRefsCursor VP8LRefsCursorInit(const VP8LBackwardRefs* const refs) { + VP8LRefsCursor c; + c.cur_block_ = refs->refs_; + if (refs->refs_ != NULL) { + c.cur_pos = c.cur_block_->start_; + c.last_pos_ = c.cur_pos + c.cur_block_->size_; + } else { + c.cur_pos = NULL; + c.last_pos_ = NULL; + } + return c; +} + +void VP8LRefsCursorNextBlock(VP8LRefsCursor* const c) { + PixOrCopyBlock* const b = c->cur_block_->next_; + c->cur_pos = (b == NULL) ? NULL : b->start_; + c->last_pos_ = (b == NULL) ? NULL : b->start_ + b->size_; + c->cur_block_ = b; +} + +// Create a new block, either from the free list or allocated +static PixOrCopyBlock* BackwardRefsNewBlock(VP8LBackwardRefs* const refs) { + PixOrCopyBlock* b = refs->free_blocks_; + if (b == NULL) { // allocate new memory chunk + const size_t total_size = + sizeof(*b) + refs->block_size_ * sizeof(*b->start_); + b = (PixOrCopyBlock*)WebPSafeMalloc(1ULL, total_size); + if (b == NULL) { + refs->error_ |= 1; + return NULL; + } + b->start_ = (PixOrCopy*)((uint8_t*)b + sizeof(*b)); // not always aligned + } else { // recycle from free-list + refs->free_blocks_ = b->next_; + } + *refs->tail_ = b; + refs->tail_ = &b->next_; + refs->last_block_ = b; + b->next_ = NULL; + b->size_ = 0; + return b; +} + +extern void VP8LBackwardRefsCursorAdd(VP8LBackwardRefs* const refs, + const PixOrCopy v); +void VP8LBackwardRefsCursorAdd(VP8LBackwardRefs* const refs, + const PixOrCopy v) { + PixOrCopyBlock* b = refs->last_block_; + if (b == NULL || b->size_ == refs->block_size_) { + b = BackwardRefsNewBlock(refs); + if (b == NULL) return; // refs->error_ is set + } + b->start_[b->size_++] = v; +} + +// ----------------------------------------------------------------------------- +// Hash chains + +int VP8LHashChainInit(VP8LHashChain* const p, int size) { + assert(p->size_ == 0); + assert(p->offset_length_ == NULL); + assert(size > 0); + p->offset_length_ = + (uint32_t*)WebPSafeMalloc(size, sizeof(*p->offset_length_)); + if (p->offset_length_ == NULL) return 0; + p->size_ = size; + + return 1; +} + +void VP8LHashChainClear(VP8LHashChain* const p) { + assert(p != NULL); + WebPSafeFree(p->offset_length_); + + p->size_ = 0; + p->offset_length_ = NULL; +} + +// ----------------------------------------------------------------------------- + +#define HASH_MULTIPLIER_HI (0xc6a4a793ULL) +#define HASH_MULTIPLIER_LO (0x5bd1e996ULL) + +static WEBP_INLINE uint32_t GetPixPairHash64(const uint32_t* const argb) { + uint32_t key; + key = (argb[1] * HASH_MULTIPLIER_HI) & 0xffffffffu; + key += (argb[0] * HASH_MULTIPLIER_LO) & 0xffffffffu; + key = key >> (32 - HASH_BITS); + return key; +} + +// Returns the maximum number of hash chain lookups to do for a +// given compression quality. Return value in range [8, 86]. +static int GetMaxItersForQuality(int quality) { + return 8 + (quality * quality) / 128; +} + +static int GetWindowSizeForHashChain(int quality, int xsize) { + const int max_window_size = (quality > 75) ? WINDOW_SIZE + : (quality > 50) ? (xsize << 8) + : (quality > 25) ? (xsize << 6) + : (xsize << 4); + assert(xsize > 0); + return (max_window_size > WINDOW_SIZE) ? WINDOW_SIZE : max_window_size; +} + +static WEBP_INLINE int MaxFindCopyLength(int len) { + return (len < MAX_LENGTH) ? len : MAX_LENGTH; +} + +int VP8LHashChainFill(VP8LHashChain* const p, int quality, + const uint32_t* const argb, int xsize, int ysize, + int low_effort) { + const int size = xsize * ysize; + const int iter_max = GetMaxItersForQuality(quality); + const uint32_t window_size = GetWindowSizeForHashChain(quality, xsize); + int pos; + int argb_comp; + uint32_t base_position; + int32_t* hash_to_first_index; + // Temporarily use the p->offset_length_ as a hash chain. + int32_t* chain = (int32_t*)p->offset_length_; + assert(size > 0); + assert(p->size_ != 0); + assert(p->offset_length_ != NULL); + + if (size <= 2) { + p->offset_length_[0] = p->offset_length_[size - 1] = 0; + return 1; + } + + hash_to_first_index = + (int32_t*)WebPSafeMalloc(HASH_SIZE, sizeof(*hash_to_first_index)); + if (hash_to_first_index == NULL) return 0; + + // Set the int32_t array to -1. + memset(hash_to_first_index, 0xff, HASH_SIZE * sizeof(*hash_to_first_index)); + // Fill the chain linking pixels with the same hash. + argb_comp = (argb[0] == argb[1]); + for (pos = 0; pos < size - 2;) { + uint32_t hash_code; + const int argb_comp_next = (argb[pos + 1] == argb[pos + 2]); + if (argb_comp && argb_comp_next) { + // Consecutive pixels with the same color will share the same hash. + // We therefore use a different hash: the color and its repetition + // length. + uint32_t tmp[2]; + uint32_t len = 1; + tmp[0] = argb[pos]; + // Figure out how far the pixels are the same. + // The last pixel has a different 64 bit hash, as its next pixel does + // not have the same color, so we just need to get to the last pixel equal + // to its follower. + while (pos + (int)len + 2 < size && argb[pos + len + 2] == argb[pos]) { + ++len; + } + if (len > MAX_LENGTH) { + // Skip the pixels that match for distance=1 and length>MAX_LENGTH + // because they are linked to their predecessor and we automatically + // check that in the main for loop below. Skipping means setting no + // predecessor in the chain, hence -1. + memset(chain + pos, 0xff, (len - MAX_LENGTH) * sizeof(*chain)); + pos += len - MAX_LENGTH; + len = MAX_LENGTH; + } + // Process the rest of the hash chain. + while (len) { + tmp[1] = len--; + hash_code = GetPixPairHash64(tmp); + chain[pos] = hash_to_first_index[hash_code]; + hash_to_first_index[hash_code] = pos++; + } + argb_comp = 0; + } else { + // Just move one pixel forward. + hash_code = GetPixPairHash64(argb + pos); + chain[pos] = hash_to_first_index[hash_code]; + hash_to_first_index[hash_code] = pos++; + argb_comp = argb_comp_next; + } + } + // Process the penultimate pixel. + chain[pos] = hash_to_first_index[GetPixPairHash64(argb + pos)]; + + WebPSafeFree(hash_to_first_index); + + // Find the best match interval at each pixel, defined by an offset to the + // pixel and a length. The right-most pixel cannot match anything to the right + // (hence a best length of 0) and the left-most pixel nothing to the left + // (hence an offset of 0). + assert(size > 2); + p->offset_length_[0] = p->offset_length_[size - 1] = 0; + for (base_position = size - 2; base_position > 0;) { + const int max_len = MaxFindCopyLength(size - 1 - base_position); + const uint32_t* const argb_start = argb + base_position; + int iter = iter_max; + int best_length = 0; + uint32_t best_distance = 0; + uint32_t best_argb; + const int min_pos = + (base_position > window_size) ? base_position - window_size : 0; + const int length_max = (max_len < 256) ? max_len : 256; + uint32_t max_base_position; + + pos = chain[base_position]; + if (!low_effort) { + int curr_length; + // Heuristic: use the comparison with the above line as an initialization. + if (base_position >= (uint32_t)xsize) { + curr_length = FindMatchLength(argb_start - xsize, argb_start, + best_length, max_len); + if (curr_length > best_length) { + best_length = curr_length; + best_distance = xsize; + } + --iter; + } + // Heuristic: compare to the previous pixel. + curr_length = + FindMatchLength(argb_start - 1, argb_start, best_length, max_len); + if (curr_length > best_length) { + best_length = curr_length; + best_distance = 1; + } + --iter; + // Skip the for loop if we already have the maximum. + if (best_length == MAX_LENGTH) pos = min_pos - 1; + } + best_argb = argb_start[best_length]; + + for (; pos >= min_pos && --iter; pos = chain[pos]) { + int curr_length; + assert(base_position > (uint32_t)pos); + + if (argb[pos + best_length] != best_argb) continue; + + curr_length = VP8LVectorMismatch(argb + pos, argb_start, max_len); + if (best_length < curr_length) { + best_length = curr_length; + best_distance = base_position - pos; + best_argb = argb_start[best_length]; + // Stop if we have reached a good enough length. + if (best_length >= length_max) break; + } + } + // We have the best match but in case the two intervals continue matching + // to the left, we have the best matches for the left-extended pixels. + max_base_position = base_position; + while (1) { + assert(best_length <= MAX_LENGTH); + assert(best_distance <= WINDOW_SIZE); + p->offset_length_[base_position] = + (best_distance << MAX_LENGTH_BITS) | (uint32_t)best_length; + --base_position; + // Stop if we don't have a match or if we are out of bounds. + if (best_distance == 0 || base_position == 0) break; + // Stop if we cannot extend the matching intervals to the left. + if (base_position < best_distance || + argb[base_position - best_distance] != argb[base_position]) { + break; + } + // Stop if we are matching at its limit because there could be a closer + // matching interval with the same maximum length. Then again, if the + // matching interval is as close as possible (best_distance == 1), we will + // never find anything better so let's continue. + if (best_length == MAX_LENGTH && best_distance != 1 && + base_position + MAX_LENGTH < max_base_position) { + break; + } + if (best_length < MAX_LENGTH) { + ++best_length; + max_base_position = base_position; + } + } + } + return 1; +} + +static WEBP_INLINE void AddSingleLiteral(uint32_t pixel, int use_color_cache, + VP8LColorCache* const hashers, + VP8LBackwardRefs* const refs) { + PixOrCopy v; + if (use_color_cache) { + const uint32_t key = VP8LColorCacheGetIndex(hashers, pixel); + if (VP8LColorCacheLookup(hashers, key) == pixel) { + v = PixOrCopyCreateCacheIdx(key); + } else { + v = PixOrCopyCreateLiteral(pixel); + VP8LColorCacheSet(hashers, key, pixel); + } + } else { + v = PixOrCopyCreateLiteral(pixel); + } + VP8LBackwardRefsCursorAdd(refs, v); +} + +static int BackwardReferencesRle(int xsize, int ysize, + const uint32_t* const argb, + int cache_bits, VP8LBackwardRefs* const refs) { + const int pix_count = xsize * ysize; + int i, k; + const int use_color_cache = (cache_bits > 0); + VP8LColorCache hashers; + + if (use_color_cache && !VP8LColorCacheInit(&hashers, cache_bits)) { + return 0; + } + VP8LClearBackwardRefs(refs); + // Add first pixel as literal. + AddSingleLiteral(argb[0], use_color_cache, &hashers, refs); + i = 1; + while (i < pix_count) { + const int max_len = MaxFindCopyLength(pix_count - i); + const int rle_len = FindMatchLength(argb + i, argb + i - 1, 0, max_len); + const int prev_row_len = (i < xsize) ? 0 : + FindMatchLength(argb + i, argb + i - xsize, 0, max_len); + if (rle_len >= prev_row_len && rle_len >= MIN_LENGTH) { + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, rle_len)); + // We don't need to update the color cache here since it is always the + // same pixel being copied, and that does not change the color cache + // state. + i += rle_len; + } else if (prev_row_len >= MIN_LENGTH) { + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(xsize, prev_row_len)); + if (use_color_cache) { + for (k = 0; k < prev_row_len; ++k) { + VP8LColorCacheInsert(&hashers, argb[i + k]); + } + } + i += prev_row_len; + } else { + AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); + i++; + } + } + if (use_color_cache) VP8LColorCacheClear(&hashers); + return !refs->error_; +} + +static int BackwardReferencesLz77(int xsize, int ysize, + const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs) { + int i; + int i_last_check = -1; + int ok = 0; + int cc_init = 0; + const int use_color_cache = (cache_bits > 0); + const int pix_count = xsize * ysize; + VP8LColorCache hashers; + + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) goto Error; + } + VP8LClearBackwardRefs(refs); + for (i = 0; i < pix_count;) { + // Alternative#1: Code the pixels starting at 'i' using backward reference. + int offset = 0; + int len = 0; + int j; + VP8LHashChainFindCopy(hash_chain, i, &offset, &len); + if (len >= MIN_LENGTH) { + const int len_ini = len; + int max_reach = 0; + const int j_max = + (i + len_ini >= pix_count) ? pix_count - 1 : i + len_ini; + // Only start from what we have not checked already. + i_last_check = (i > i_last_check) ? i : i_last_check; + // We know the best match for the current pixel but we try to find the + // best matches for the current pixel AND the next one combined. + // The naive method would use the intervals: + // [i,i+len) + [i+len, length of best match at i+len) + // while we check if we can use: + // [i,j) (where j<=i+len) + [j, length of best match at j) + for (j = i_last_check + 1; j <= j_max; ++j) { + const int len_j = VP8LHashChainFindLength(hash_chain, j); + const int reach = + j + (len_j >= MIN_LENGTH ? len_j : 1); // 1 for single literal. + if (reach > max_reach) { + len = j - i; + max_reach = reach; + if (max_reach >= pix_count) break; + } + } + } else { + len = 1; + } + // Go with literal or backward reference. + assert(len > 0); + if (len == 1) { + AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); + } else { + VP8LBackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(offset, len)); + if (use_color_cache) { + for (j = i; j < i + len; ++j) VP8LColorCacheInsert(&hashers, argb[j]); + } + } + i += len; + } + + ok = !refs->error_; + Error: + if (cc_init) VP8LColorCacheClear(&hashers); + return ok; +} + +// Compute an LZ77 by forcing matches to happen within a given distance cost. +// We therefore limit the algorithm to the lowest 32 values in the PlaneCode +// definition. +#define WINDOW_OFFSETS_SIZE_MAX 32 +static int BackwardReferencesLz77Box(int xsize, int ysize, + const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain_best, + VP8LHashChain* hash_chain, + VP8LBackwardRefs* const refs) { + int i; + const int pix_count = xsize * ysize; + uint16_t* counts; + int window_offsets[WINDOW_OFFSETS_SIZE_MAX] = {0}; + int window_offsets_new[WINDOW_OFFSETS_SIZE_MAX] = {0}; + int window_offsets_size = 0; + int window_offsets_new_size = 0; + uint16_t* const counts_ini = + (uint16_t*)WebPSafeMalloc(xsize * ysize, sizeof(*counts_ini)); + int best_offset_prev = -1, best_length_prev = -1; + if (counts_ini == NULL) return 0; + + // counts[i] counts how many times a pixel is repeated starting at position i. + i = pix_count - 2; + counts = counts_ini + i; + counts[1] = 1; + for (; i >= 0; --i, --counts) { + if (argb[i] == argb[i + 1]) { + // Max out the counts to MAX_LENGTH. + counts[0] = counts[1] + (counts[1] != MAX_LENGTH); + } else { + counts[0] = 1; + } + } + + // Figure out the window offsets around a pixel. They are stored in a + // spiraling order around the pixel as defined by VP8LDistanceToPlaneCode. + { + int x, y; + for (y = 0; y <= 6; ++y) { + for (x = -6; x <= 6; ++x) { + const int offset = y * xsize + x; + int plane_code; + // Ignore offsets that bring us after the pixel. + if (offset <= 0) continue; + plane_code = VP8LDistanceToPlaneCode(xsize, offset) - 1; + if (plane_code >= WINDOW_OFFSETS_SIZE_MAX) continue; + window_offsets[plane_code] = offset; + } + } + // For narrow images, not all plane codes are reached, so remove those. + for (i = 0; i < WINDOW_OFFSETS_SIZE_MAX; ++i) { + if (window_offsets[i] == 0) continue; + window_offsets[window_offsets_size++] = window_offsets[i]; + } + // Given a pixel P, find the offsets that reach pixels unreachable from P-1 + // with any of the offsets in window_offsets[]. + for (i = 0; i < window_offsets_size; ++i) { + int j; + int is_reachable = 0; + for (j = 0; j < window_offsets_size && !is_reachable; ++j) { + is_reachable |= (window_offsets[i] == window_offsets[j] + 1); + } + if (!is_reachable) { + window_offsets_new[window_offsets_new_size] = window_offsets[i]; + ++window_offsets_new_size; + } + } + } + + hash_chain->offset_length_[0] = 0; + for (i = 1; i < pix_count; ++i) { + int ind; + int best_length = VP8LHashChainFindLength(hash_chain_best, i); + int best_offset; + int do_compute = 1; + + if (best_length >= MAX_LENGTH) { + // Do not recompute the best match if we already have a maximal one in the + // window. + best_offset = VP8LHashChainFindOffset(hash_chain_best, i); + for (ind = 0; ind < window_offsets_size; ++ind) { + if (best_offset == window_offsets[ind]) { + do_compute = 0; + break; + } + } + } + if (do_compute) { + // Figure out if we should use the offset/length from the previous pixel + // as an initial guess and therefore only inspect the offsets in + // window_offsets_new[]. + const int use_prev = + (best_length_prev > 1) && (best_length_prev < MAX_LENGTH); + const int num_ind = + use_prev ? window_offsets_new_size : window_offsets_size; + best_length = use_prev ? best_length_prev - 1 : 0; + best_offset = use_prev ? best_offset_prev : 0; + // Find the longest match in a window around the pixel. + for (ind = 0; ind < num_ind; ++ind) { + int curr_length = 0; + int j = i; + int j_offset = + use_prev ? i - window_offsets_new[ind] : i - window_offsets[ind]; + if (j_offset < 0 || argb[j_offset] != argb[i]) continue; + // The longest match is the sum of how many times each pixel is + // repeated. + do { + const int counts_j_offset = counts_ini[j_offset]; + const int counts_j = counts_ini[j]; + if (counts_j_offset != counts_j) { + curr_length += + (counts_j_offset < counts_j) ? counts_j_offset : counts_j; + break; + } + // The same color is repeated counts_pos times at j_offset and j. + curr_length += counts_j_offset; + j_offset += counts_j_offset; + j += counts_j_offset; + } while (curr_length <= MAX_LENGTH && j < pix_count && + argb[j_offset] == argb[j]); + if (best_length < curr_length) { + best_offset = + use_prev ? window_offsets_new[ind] : window_offsets[ind]; + if (curr_length >= MAX_LENGTH) { + best_length = MAX_LENGTH; + break; + } else { + best_length = curr_length; + } + } + } + } + + assert(i + best_length <= pix_count); + assert(best_length <= MAX_LENGTH); + if (best_length <= MIN_LENGTH) { + hash_chain->offset_length_[i] = 0; + best_offset_prev = 0; + best_length_prev = 0; + } else { + hash_chain->offset_length_[i] = + (best_offset << MAX_LENGTH_BITS) | (uint32_t)best_length; + best_offset_prev = best_offset; + best_length_prev = best_length; + } + } + hash_chain->offset_length_[0] = 0; + WebPSafeFree(counts_ini); + + return BackwardReferencesLz77(xsize, ysize, argb, cache_bits, hash_chain, + refs); +} + +// ----------------------------------------------------------------------------- + +static void BackwardReferences2DLocality(int xsize, + const VP8LBackwardRefs* const refs) { + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + while (VP8LRefsCursorOk(&c)) { + if (PixOrCopyIsCopy(c.cur_pos)) { + const int dist = c.cur_pos->argb_or_distance; + const int transformed_dist = VP8LDistanceToPlaneCode(xsize, dist); + c.cur_pos->argb_or_distance = transformed_dist; + } + VP8LRefsCursorNext(&c); + } +} + +// Evaluate optimal cache bits for the local color cache. +// The input *best_cache_bits sets the maximum cache bits to use (passing 0 +// implies disabling the local color cache). The local color cache is also +// disabled for the lower (<= 25) quality. +// Returns 0 in case of memory error. +static int CalculateBestCacheSize(const uint32_t* argb, int quality, + const VP8LBackwardRefs* const refs, + int* const best_cache_bits) { + int i; + const int cache_bits_max = (quality <= 25) ? 0 : *best_cache_bits; + double entropy_min = MAX_ENTROPY; + int cc_init[MAX_COLOR_CACHE_BITS + 1] = { 0 }; + VP8LColorCache hashers[MAX_COLOR_CACHE_BITS + 1]; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + VP8LHistogram* histos[MAX_COLOR_CACHE_BITS + 1] = { NULL }; + int ok = 0; + + assert(cache_bits_max >= 0 && cache_bits_max <= MAX_COLOR_CACHE_BITS); + + if (cache_bits_max == 0) { + *best_cache_bits = 0; + // Local color cache is disabled. + return 1; + } + + // Allocate data. + for (i = 0; i <= cache_bits_max; ++i) { + histos[i] = VP8LAllocateHistogram(i); + if (histos[i] == NULL) goto Error; + if (i == 0) continue; + cc_init[i] = VP8LColorCacheInit(&hashers[i], i); + if (!cc_init[i]) goto Error; + } + + // Find the cache_bits giving the lowest entropy. The search is done in a + // brute-force way as the function (entropy w.r.t cache_bits) can be + // anything in practice. + while (VP8LRefsCursorOk(&c)) { + const PixOrCopy* const v = c.cur_pos; + if (PixOrCopyIsLiteral(v)) { + const uint32_t pix = *argb++; + const uint32_t a = (pix >> 24) & 0xff; + const uint32_t r = (pix >> 16) & 0xff; + const uint32_t g = (pix >> 8) & 0xff; + const uint32_t b = (pix >> 0) & 0xff; + // The keys of the caches can be derived from the longest one. + int key = VP8LHashPix(pix, 32 - cache_bits_max); + // Do not use the color cache for cache_bits = 0. + ++histos[0]->blue_[b]; + ++histos[0]->literal_[g]; + ++histos[0]->red_[r]; + ++histos[0]->alpha_[a]; + // Deal with cache_bits > 0. + for (i = cache_bits_max; i >= 1; --i, key >>= 1) { + if (VP8LColorCacheLookup(&hashers[i], key) == pix) { + ++histos[i]->literal_[NUM_LITERAL_CODES + NUM_LENGTH_CODES + key]; + } else { + VP8LColorCacheSet(&hashers[i], key, pix); + ++histos[i]->blue_[b]; + ++histos[i]->literal_[g]; + ++histos[i]->red_[r]; + ++histos[i]->alpha_[a]; + } + } + } else { + // We should compute the contribution of the (distance,length) + // histograms but those are the same independently from the cache size. + // As those constant contributions are in the end added to the other + // histogram contributions, we can safely ignore them. + int len = PixOrCopyLength(v); + uint32_t argb_prev = *argb ^ 0xffffffffu; + // Update the color caches. + do { + if (*argb != argb_prev) { + // Efficiency: insert only if the color changes. + int key = VP8LHashPix(*argb, 32 - cache_bits_max); + for (i = cache_bits_max; i >= 1; --i, key >>= 1) { + hashers[i].colors_[key] = *argb; + } + argb_prev = *argb; + } + argb++; + } while (--len != 0); + } + VP8LRefsCursorNext(&c); + } + + for (i = 0; i <= cache_bits_max; ++i) { + const double entropy = VP8LHistogramEstimateBits(histos[i]); + if (i == 0 || entropy < entropy_min) { + entropy_min = entropy; + *best_cache_bits = i; + } + } + ok = 1; +Error: + for (i = 0; i <= cache_bits_max; ++i) { + if (cc_init[i]) VP8LColorCacheClear(&hashers[i]); + VP8LFreeHistogram(histos[i]); + } + return ok; +} + +// Update (in-place) backward references for specified cache_bits. +static int BackwardRefsWithLocalCache(const uint32_t* const argb, + int cache_bits, + VP8LBackwardRefs* const refs) { + int pixel_index = 0; + VP8LColorCache hashers; + VP8LRefsCursor c = VP8LRefsCursorInit(refs); + if (!VP8LColorCacheInit(&hashers, cache_bits)) return 0; + + while (VP8LRefsCursorOk(&c)) { + PixOrCopy* const v = c.cur_pos; + if (PixOrCopyIsLiteral(v)) { + const uint32_t argb_literal = v->argb_or_distance; + const int ix = VP8LColorCacheContains(&hashers, argb_literal); + if (ix >= 0) { + // hashers contains argb_literal + *v = PixOrCopyCreateCacheIdx(ix); + } else { + VP8LColorCacheInsert(&hashers, argb_literal); + } + ++pixel_index; + } else { + // refs was created without local cache, so it can not have cache indexes. + int k; + assert(PixOrCopyIsCopy(v)); + for (k = 0; k < v->len; ++k) { + VP8LColorCacheInsert(&hashers, argb[pixel_index++]); + } + } + VP8LRefsCursorNext(&c); + } + VP8LColorCacheClear(&hashers); + return 1; +} + +static VP8LBackwardRefs* GetBackwardReferencesLowEffort( + int width, int height, const uint32_t* const argb, + int* const cache_bits, const VP8LHashChain* const hash_chain, + VP8LBackwardRefs* const refs_lz77) { + *cache_bits = 0; + if (!BackwardReferencesLz77(width, height, argb, 0, hash_chain, refs_lz77)) { + return NULL; + } + BackwardReferences2DLocality(width, refs_lz77); + return refs_lz77; +} + +extern int VP8LBackwardReferencesTraceBackwards( + int xsize, int ysize, const uint32_t* const argb, int cache_bits, + const VP8LHashChain* const hash_chain, + const VP8LBackwardRefs* const refs_src, VP8LBackwardRefs* const refs_dst); +static VP8LBackwardRefs* GetBackwardReferences( + int width, int height, const uint32_t* const argb, int quality, + int lz77_types_to_try, int* const cache_bits, + const VP8LHashChain* const hash_chain, VP8LBackwardRefs* best, + VP8LBackwardRefs* worst) { + const int cache_bits_initial = *cache_bits; + double bit_cost_best = -1; + VP8LHistogram* histo = NULL; + int lz77_type, lz77_type_best = 0; + VP8LHashChain hash_chain_box; + memset(&hash_chain_box, 0, sizeof(hash_chain_box)); + + histo = VP8LAllocateHistogram(MAX_COLOR_CACHE_BITS); + if (histo == NULL) goto Error; + + for (lz77_type = 1; lz77_types_to_try; + lz77_types_to_try &= ~lz77_type, lz77_type <<= 1) { + int res = 0; + double bit_cost; + int cache_bits_tmp = cache_bits_initial; + if ((lz77_types_to_try & lz77_type) == 0) continue; + switch (lz77_type) { + case kLZ77RLE: + res = BackwardReferencesRle(width, height, argb, 0, worst); + break; + case kLZ77Standard: + // Compute LZ77 with no cache (0 bits), as the ideal LZ77 with a color + // cache is not that different in practice. + res = BackwardReferencesLz77(width, height, argb, 0, hash_chain, worst); + break; + case kLZ77Box: + if (!VP8LHashChainInit(&hash_chain_box, width * height)) goto Error; + res = BackwardReferencesLz77Box(width, height, argb, 0, hash_chain, + &hash_chain_box, worst); + break; + default: + assert(0); + } + if (!res) goto Error; + + // Next, try with a color cache and update the references. + if (!CalculateBestCacheSize(argb, quality, worst, &cache_bits_tmp)) { + goto Error; + } + if (cache_bits_tmp > 0) { + if (!BackwardRefsWithLocalCache(argb, cache_bits_tmp, worst)) { + goto Error; + } + } + + // Keep the best backward references. + VP8LHistogramCreate(histo, worst, cache_bits_tmp); + bit_cost = VP8LHistogramEstimateBits(histo); + if (lz77_type_best == 0 || bit_cost < bit_cost_best) { + VP8LBackwardRefs* const tmp = worst; + worst = best; + best = tmp; + bit_cost_best = bit_cost; + *cache_bits = cache_bits_tmp; + lz77_type_best = lz77_type; + } + } + assert(lz77_type_best > 0); + + // Improve on simple LZ77 but only for high quality (TraceBackwards is + // costly). + if ((lz77_type_best == kLZ77Standard || lz77_type_best == kLZ77Box) && + quality >= 25) { + const VP8LHashChain* const hash_chain_tmp = + (lz77_type_best == kLZ77Standard) ? hash_chain : &hash_chain_box; + if (VP8LBackwardReferencesTraceBackwards(width, height, argb, *cache_bits, + hash_chain_tmp, best, worst)) { + double bit_cost_trace; + VP8LHistogramCreate(histo, worst, *cache_bits); + bit_cost_trace = VP8LHistogramEstimateBits(histo); + if (bit_cost_trace < bit_cost_best) best = worst; + } + } + + BackwardReferences2DLocality(width, best); + +Error: + VP8LHashChainClear(&hash_chain_box); + VP8LFreeHistogram(histo); + return best; +} + +VP8LBackwardRefs* VP8LGetBackwardReferences( + int width, int height, const uint32_t* const argb, int quality, + int low_effort, int lz77_types_to_try, int* const cache_bits, + const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs_tmp1, + VP8LBackwardRefs* const refs_tmp2) { + if (low_effort) { + return GetBackwardReferencesLowEffort(width, height, argb, cache_bits, + hash_chain, refs_tmp1); + } else { + return GetBackwardReferences(width, height, argb, quality, + lz77_types_to_try, cache_bits, hash_chain, + refs_tmp1, refs_tmp2); + } +} diff --git a/3rdparty/libwebp/enc/backward_references_enc.h b/3rdparty/libwebp/src/enc/backward_references_enc.h similarity index 79% rename from 3rdparty/libwebp/enc/backward_references_enc.h rename to 3rdparty/libwebp/src/enc/backward_references_enc.h index 3a19aa763e..103ddfdcb7 100644 --- a/3rdparty/libwebp/enc/backward_references_enc.h +++ b/3rdparty/libwebp/src/enc/backward_references_enc.h @@ -10,13 +10,13 @@ // Author: Jyrki Alakuijala (jyrki@google.com) // -#ifndef WEBP_ENC_BACKWARD_REFERENCES_H_ -#define WEBP_ENC_BACKWARD_REFERENCES_H_ +#ifndef WEBP_ENC_BACKWARD_REFERENCES_ENC_H_ +#define WEBP_ENC_BACKWARD_REFERENCES_ENC_H_ #include #include -#include "../webp/types.h" -#include "../webp/format_constants.h" +#include "src/webp/types.h" +#include "src/webp/format_constants.h" #ifdef __cplusplus extern "C" { @@ -91,11 +91,6 @@ static WEBP_INLINE uint32_t PixOrCopyLength(const PixOrCopy* const p) { return p->len; } -static WEBP_INLINE uint32_t PixOrCopyArgb(const PixOrCopy* const p) { - assert(p->mode == kLiteral); - return p->argb_or_distance; -} - static WEBP_INLINE uint32_t PixOrCopyCacheIdx(const PixOrCopy* const p) { assert(p->mode == kCacheIdx); assert(p->argb_or_distance < (1U << MAX_COLOR_CACHE_BITS)); @@ -113,6 +108,16 @@ static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) { #define HASH_BITS 18 #define HASH_SIZE (1 << HASH_BITS) +// If you change this, you need MAX_LENGTH_BITS + WINDOW_SIZE_BITS <= 32 as it +// is used in VP8LHashChain. +#define MAX_LENGTH_BITS 12 +#define WINDOW_SIZE_BITS 20 +// We want the max value to be attainable and stored in MAX_LENGTH_BITS bits. +#define MAX_LENGTH ((1 << MAX_LENGTH_BITS) - 1) +#if MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32 +#error "MAX_LENGTH_BITS + WINDOW_SIZE_BITS > 32" +#endif + typedef struct VP8LHashChain VP8LHashChain; struct VP8LHashChain { // The 20 most significant bits contain the offset at which the best match @@ -134,6 +139,24 @@ int VP8LHashChainFill(VP8LHashChain* const p, int quality, int low_effort); void VP8LHashChainClear(VP8LHashChain* const p); // release memory +static WEBP_INLINE int VP8LHashChainFindOffset(const VP8LHashChain* const p, + const int base_position) { + return p->offset_length_[base_position] >> MAX_LENGTH_BITS; +} + +static WEBP_INLINE int VP8LHashChainFindLength(const VP8LHashChain* const p, + const int base_position) { + return p->offset_length_[base_position] & ((1U << MAX_LENGTH_BITS) - 1); +} + +static WEBP_INLINE void VP8LHashChainFindCopy(const VP8LHashChain* const p, + int base_position, + int* const offset_ptr, + int* const length_ptr) { + *offset_ptr = VP8LHashChainFindOffset(p, base_position); + *length_ptr = VP8LHashChainFindLength(p, base_position); +} + // ----------------------------------------------------------------------------- // VP8LBackwardRefs (block-based backward-references storage) @@ -158,9 +181,6 @@ struct VP8LBackwardRefs { void VP8LBackwardRefsInit(VP8LBackwardRefs* const refs, int block_size); // Release memory for backward references. void VP8LBackwardRefsClear(VP8LBackwardRefs* const refs); -// Copies the 'src' backward refs to the 'dst'. Returns 0 in case of error. -int VP8LBackwardRefsCopy(const VP8LBackwardRefs* const src, - VP8LBackwardRefs* const dst); // Cursor for iterating on references content typedef struct { @@ -189,6 +209,12 @@ static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) { // ----------------------------------------------------------------------------- // Main entry points +enum VP8LLZ77Type { + kLZ77Standard = 1, + kLZ77RLE = 2, + kLZ77Box = 4 +}; + // Evaluates best possible backward references for specified quality. // The input cache_bits to 'VP8LGetBackwardReferences' sets the maximum cache // bits to use (passing 0 implies disabling the local color cache). @@ -197,11 +223,12 @@ static WEBP_INLINE void VP8LRefsCursorNext(VP8LRefsCursor* const c) { // refs[0] or refs[1]. VP8LBackwardRefs* VP8LGetBackwardReferences( int width, int height, const uint32_t* const argb, int quality, - int low_effort, int* const cache_bits, - const VP8LHashChain* const hash_chain, VP8LBackwardRefs refs[2]); + int low_effort, int lz77_types_to_try, int* const cache_bits, + const VP8LHashChain* const hash_chain, VP8LBackwardRefs* const refs_tmp1, + VP8LBackwardRefs* const refs_tmp2); #ifdef __cplusplus } #endif -#endif // WEBP_ENC_BACKWARD_REFERENCES_H_ +#endif // WEBP_ENC_BACKWARD_REFERENCES_ENC_H_ diff --git a/3rdparty/libwebp/enc/config_enc.c b/3rdparty/libwebp/src/enc/config_enc.c similarity index 98% rename from 3rdparty/libwebp/enc/config_enc.c rename to 3rdparty/libwebp/src/enc/config_enc.c index 4589dc0619..9d4828978e 100644 --- a/3rdparty/libwebp/enc/config_enc.c +++ b/3rdparty/libwebp/src/enc/config_enc.c @@ -12,10 +12,10 @@ // Author: Skal (pascal.massimino@gmail.com) #ifdef HAVE_CONFIG_H -#include "../webp/config.h" +#include "src/webp/config.h" #endif -#include "../webp/encode.h" +#include "src/webp/encode.h" //------------------------------------------------------------------------------ // WebPConfig diff --git a/3rdparty/libwebp/enc/cost_enc.c b/3rdparty/libwebp/src/enc/cost_enc.c similarity index 99% rename from 3rdparty/libwebp/enc/cost_enc.c rename to 3rdparty/libwebp/src/enc/cost_enc.c index c823f5a664..48fd9bc347 100644 --- a/3rdparty/libwebp/enc/cost_enc.c +++ b/3rdparty/libwebp/src/enc/cost_enc.c @@ -11,7 +11,7 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./cost_enc.h" +#include "src/enc/cost_enc.h" //------------------------------------------------------------------------------ // Level cost tables diff --git a/3rdparty/libwebp/enc/cost_enc.h b/3rdparty/libwebp/src/enc/cost_enc.h similarity index 95% rename from 3rdparty/libwebp/enc/cost_enc.h rename to 3rdparty/libwebp/src/enc/cost_enc.h index 99e4b37aa3..bdce1e6a3b 100644 --- a/3rdparty/libwebp/enc/cost_enc.h +++ b/3rdparty/libwebp/src/enc/cost_enc.h @@ -11,12 +11,12 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_ENC_COST_H_ -#define WEBP_ENC_COST_H_ +#ifndef WEBP_ENC_COST_ENC_H_ +#define WEBP_ENC_COST_ENC_H_ #include #include -#include "./vp8i_enc.h" +#include "src/enc/vp8i_enc.h" #ifdef __cplusplus extern "C" { @@ -79,4 +79,4 @@ extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES]; } // extern "C" #endif -#endif /* WEBP_ENC_COST_H_ */ +#endif /* WEBP_ENC_COST_ENC_H_ */ diff --git a/3rdparty/libwebp/enc/delta_palettization_enc.c b/3rdparty/libwebp/src/enc/delta_palettization_enc.c similarity index 99% rename from 3rdparty/libwebp/enc/delta_palettization_enc.c rename to 3rdparty/libwebp/src/enc/delta_palettization_enc.c index eaf0f050ea..a61c8e6c93 100644 --- a/3rdparty/libwebp/enc/delta_palettization_enc.c +++ b/3rdparty/libwebp/src/enc/delta_palettization_enc.c @@ -10,11 +10,11 @@ // Author: Mislav Bradac (mislavm@google.com) // -#include "./delta_palettization_enc.h" +#include "src/enc/delta_palettization_enc.h" #ifdef WEBP_EXPERIMENTAL_FEATURES -#include "../webp/types.h" -#include "../dsp/lossless.h" +#include "src/webp/types.h" +#include "src/dsp/lossless.h" #define MK_COL(r, g, b) (((r) << 16) + ((g) << 8) + (b)) diff --git a/3rdparty/libwebp/enc/delta_palettization_enc.h b/3rdparty/libwebp/src/enc/delta_palettization_enc.h similarity index 81% rename from 3rdparty/libwebp/enc/delta_palettization_enc.h rename to 3rdparty/libwebp/src/enc/delta_palettization_enc.h index 63048ec6e8..b15e2cd487 100644 --- a/3rdparty/libwebp/enc/delta_palettization_enc.h +++ b/3rdparty/libwebp/src/enc/delta_palettization_enc.h @@ -10,11 +10,11 @@ // Author: Mislav Bradac (mislavm@google.com) // -#ifndef WEBP_ENC_DELTA_PALETTIZATION_H_ -#define WEBP_ENC_DELTA_PALETTIZATION_H_ +#ifndef WEBP_ENC_DELTA_PALETTIZATION_ENC_H_ +#define WEBP_ENC_DELTA_PALETTIZATION_ENC_H_ -#include "../webp/encode.h" -#include "../enc/vp8li_enc.h" +#include "src/webp/encode.h" +#include "src/enc/vp8li_enc.h" // Replaces enc->argb_[] input by a palettizable approximation of it, // and generates optimal enc->palette_[]. @@ -22,4 +22,4 @@ // if delta-palettization is not producing expected saving. WebPEncodingError WebPSearchOptimalDeltaPalette(VP8LEncoder* const enc); -#endif // WEBP_ENC_DELTA_PALETTIZATION_H_ +#endif // WEBP_ENC_DELTA_PALETTIZATION_ENC_H_ diff --git a/3rdparty/libwebp/enc/filter_enc.c b/3rdparty/libwebp/src/enc/filter_enc.c similarity index 95% rename from 3rdparty/libwebp/enc/filter_enc.c rename to 3rdparty/libwebp/src/enc/filter_enc.c index 4bc367274c..580800bfb8 100644 --- a/3rdparty/libwebp/enc/filter_enc.c +++ b/3rdparty/libwebp/src/enc/filter_enc.c @@ -12,8 +12,8 @@ // Author: somnath@google.com (Somnath Banerjee) #include -#include "./vp8i_enc.h" -#include "../dsp/dsp.h" +#include "src/enc/vp8i_enc.h" +#include "src/dsp/dsp.h" // This table gives, for a given sharpness, the filtering strength to be // used (at least) in order to filter a given edge step delta. @@ -65,6 +65,8 @@ int VP8FilterStrengthFromDelta(int sharpness, int delta) { //------------------------------------------------------------------------------ // Paragraph 15.4: compute the inner-edge filtering strength +#if !defined(WEBP_REDUCE_SIZE) + static int GetILevel(int sharpness, int level) { if (sharpness > 0) { if (sharpness > 4) { @@ -129,11 +131,14 @@ static double GetMBSSIM(const uint8_t* yuv1, const uint8_t* yuv2) { return sum; } +#endif // !defined(WEBP_REDUCE_SIZE) + //------------------------------------------------------------------------------ // Exposed APIs: Encoder should call the following 3 functions to adjust // loop filter strength void VP8InitFilter(VP8EncIterator* const it) { +#if !defined(WEBP_REDUCE_SIZE) if (it->lf_stats_ != NULL) { int s, i; for (s = 0; s < NUM_MB_SEGMENTS; s++) { @@ -143,9 +148,13 @@ void VP8InitFilter(VP8EncIterator* const it) { } VP8SSIMDspInit(); } +#else + (void)it; +#endif } void VP8StoreFilterStats(VP8EncIterator* const it) { +#if !defined(WEBP_REDUCE_SIZE) int d; VP8Encoder* const enc = it->enc_; const int s = it->mb_->segment_; @@ -177,10 +186,14 @@ void VP8StoreFilterStats(VP8EncIterator* const it) { DoFilter(it, level); (*it->lf_stats_)[s][level] += GetMBSSIM(it->yuv_in_, it->yuv_out2_); } +#else // defined(WEBP_REDUCE_SIZE) + (void)it; +#endif // !defined(WEBP_REDUCE_SIZE) } void VP8AdjustFilterStrength(VP8EncIterator* const it) { VP8Encoder* const enc = it->enc_; +#if !defined(WEBP_REDUCE_SIZE) if (it->lf_stats_ != NULL) { int s; for (s = 0; s < NUM_MB_SEGMENTS; s++) { @@ -196,7 +209,10 @@ void VP8AdjustFilterStrength(VP8EncIterator* const it) { } enc->dqm_[s].fstrength_ = best_level; } - } else if (enc->config_->filter_strength > 0) { + return; + } +#endif // !defined(WEBP_REDUCE_SIZE) + if (enc->config_->filter_strength > 0) { int max_level = 0; int s; for (s = 0; s < NUM_MB_SEGMENTS; s++) { diff --git a/3rdparty/libwebp/enc/frame_enc.c b/3rdparty/libwebp/src/enc/frame_enc.c similarity index 97% rename from 3rdparty/libwebp/enc/frame_enc.c rename to 3rdparty/libwebp/src/enc/frame_enc.c index abef523bbf..2b0dc66410 100644 --- a/3rdparty/libwebp/enc/frame_enc.c +++ b/3rdparty/libwebp/src/enc/frame_enc.c @@ -14,10 +14,10 @@ #include #include -#include "./cost_enc.h" -#include "./vp8i_enc.h" -#include "../dsp/dsp.h" -#include "../webp/format_constants.h" // RIFF constants +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/dsp/dsp.h" +#include "src/webp/format_constants.h" // RIFF constants #define SEGMENT_VISU 0 #define DEBUG_SEARCH 0 // useful to track search convergence @@ -200,11 +200,13 @@ static void SetSegmentProbas(VP8Encoder* const enc) { const VP8MBInfo* const mb = &enc->mb_info_[n]; p[mb->segment_]++; } +#if !defined(WEBP_DISABLE_STATS) if (enc->pic_->stats != NULL) { for (n = 0; n < NUM_MB_SEGMENTS; ++n) { enc->pic_->stats->segment_size[n] = p[n]; } } +#endif if (enc->segment_hdr_.num_segments_ > 1) { uint8_t* const probas = enc->proba_.segments_; probas[0] = GetProba(p[0] + p[1], p[2] + p[3]); @@ -452,6 +454,8 @@ static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, //------------------------------------------------------------------------------ // ExtraInfo map / Debug function +#if !defined(WEBP_DISABLE_STATS) + #if SEGMENT_VISU static void SetBlock(uint8_t* p, int value, int size) { int y; @@ -516,6 +520,20 @@ static void StoreSideInfo(const VP8EncIterator* const it) { #endif } +#else // defined(WEBP_DISABLE_STATS) +static void ResetSSE(VP8Encoder* const enc) { + (void)enc; +} +static void StoreSideInfo(const VP8EncIterator* const it) { + VP8Encoder* const enc = it->enc_; + WebPPicture* const pic = enc->pic_; + if (pic->extra_info != NULL) { + memset(pic->extra_info, 0, + enc->mb_w_ * enc->mb_h_ * sizeof(*pic->extra_info)); + } +} +#endif // !defined(WEBP_DISABLE_STATS) + static double GetPSNR(uint64_t mse, uint64_t size) { return (mse > 0 && size > 0) ? 10. * log10(255. * 255. * size / mse) : 99; } @@ -640,7 +658,7 @@ static int StatLoop(VP8Encoder* const enc) { // Main loops // -static const int kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; +static const uint8_t kAverageBytesPerMB[8] = { 50, 24, 16, 9, 7, 5, 3, 2 }; static int PreLoopInitialize(VP8Encoder* const enc) { int p; @@ -670,6 +688,7 @@ static int PostLoopFinalize(VP8EncIterator* const it, int ok) { } if (ok) { // All good. Finish up. +#if !defined(WEBP_DISABLE_STATS) if (enc->pic_->stats != NULL) { // finalize byte counters... int i, s; for (i = 0; i <= 2; ++i) { @@ -678,6 +697,7 @@ static int PostLoopFinalize(VP8EncIterator* const it, int ok) { } } } +#endif VP8AdjustFilterStrength(it); // ...and store filter stats. } else { // Something bad happened -> need to do some memory cleanup. diff --git a/3rdparty/libwebp/enc/histogram_enc.c b/3rdparty/libwebp/src/enc/histogram_enc.c similarity index 78% rename from 3rdparty/libwebp/enc/histogram_enc.c rename to 3rdparty/libwebp/src/enc/histogram_enc.c index 808b6f78ab..056a972dda 100644 --- a/3rdparty/libwebp/enc/histogram_enc.c +++ b/3rdparty/libwebp/src/enc/histogram_enc.c @@ -10,16 +10,16 @@ // Author: Jyrki Alakuijala (jyrki@google.com) // #ifdef HAVE_CONFIG_H -#include "../webp/config.h" +#include "src/webp/config.h" #endif #include -#include "./backward_references_enc.h" -#include "./histogram_enc.h" -#include "../dsp/lossless.h" -#include "../dsp/lossless_common.h" -#include "../utils/utils.h" +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/utils/utils.h" #define MAX_COST 1.e38 @@ -76,7 +76,7 @@ void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs, VP8LHistogram* const histo) { VP8LRefsCursor c = VP8LRefsCursorInit(refs); while (VP8LRefsCursorOk(&c)) { - VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos); + VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos, NULL, 0); VP8LRefsCursorNext(&c); } } @@ -138,7 +138,9 @@ VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits) { // ----------------------------------------------------------------------------- void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, - const PixOrCopy* const v) { + const PixOrCopy* const v, + int (*const distance_modifier)(int, int), + int distance_modifier_arg0) { if (PixOrCopyIsLiteral(v)) { ++histo->alpha_[PixOrCopyLiteral(v, 3)]; ++histo->red_[PixOrCopyLiteral(v, 2)]; @@ -152,7 +154,13 @@ void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, int code, extra_bits; VP8LPrefixEncodeBits(PixOrCopyLength(v), &code, &extra_bits); ++histo->literal_[NUM_LITERAL_CODES + code]; - VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits); + if (distance_modifier == NULL) { + VP8LPrefixEncodeBits(PixOrCopyDistance(v), &code, &extra_bits); + } else { + VP8LPrefixEncodeBits( + distance_modifier(distance_modifier_arg0, PixOrCopyDistance(v)), + &code, &extra_bits); + } ++histo->distance_[code]; } } @@ -473,7 +481,7 @@ static void HistogramBuild( while (VP8LRefsCursorOk(&c)) { const PixOrCopy* const v = c.cur_pos; const int ix = (y >> histo_bits) * histo_xsize + (x >> histo_bits); - VP8LHistogramAddSinglePixOrCopy(histograms[ix], v); + VP8LHistogramAddSinglePixOrCopy(histograms[ix], v, NULL, 0); x += PixOrCopyLength(v); while (x >= xsize) { x -= xsize; @@ -523,11 +531,12 @@ static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo, // Compact image_histo[] by merging some histograms with same bin_id together if // it's advantageous. -static VP8LHistogram* HistogramCombineEntropyBin( - VP8LHistogramSet* const image_histo, - VP8LHistogram* cur_combo, - const uint16_t* const bin_map, int bin_map_size, int num_bins, - double combine_cost_factor, int low_effort) { +static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo, + VP8LHistogram* cur_combo, + const uint16_t* const bin_map, + int bin_map_size, int num_bins, + double combine_cost_factor, + int low_effort) { VP8LHistogram** const histograms = image_histo->histograms; int idx; // Work in-place: processed histograms are put at the beginning of @@ -593,14 +602,13 @@ static VP8LHistogram* HistogramCombineEntropyBin( UpdateHistogramCost(histograms[idx]); } } - return cur_combo; } +// Implement a Lehmer random number generator with a multiplicative constant of +// 48271 and a modulo constant of 2^31 − 1. static uint32_t MyRand(uint32_t* const seed) { - *seed = (*seed * 16807ull) & 0xffffffffu; - if (*seed == 0) { - *seed = 1; - } + *seed = (uint32_t)(((uint64_t)(*seed) * 48271u) % 2147483647u); + assert(*seed > 0); return *seed; } @@ -641,57 +649,75 @@ static int HistoQueueInit(HistoQueue* const histo_queue, const int max_index) { static void HistoQueueClear(HistoQueue* const histo_queue) { assert(histo_queue != NULL); WebPSafeFree(histo_queue->queue); + histo_queue->size = 0; + histo_queue->max_size = 0; } -static void SwapHistogramPairs(HistogramPair *p1, - HistogramPair *p2) { - const HistogramPair tmp = *p1; - *p1 = *p2; - *p2 = tmp; +// Pop a specific pair in the queue by replacing it with the last one +// and shrinking the queue. +static void HistoQueuePopPair(HistoQueue* const histo_queue, + HistogramPair* const pair) { + assert(pair >= histo_queue->queue && + pair < (histo_queue->queue + histo_queue->size)); + assert(histo_queue->size > 0); + *pair = histo_queue->queue[histo_queue->size - 1]; + --histo_queue->size; } -// Given a valid priority queue in range [0, queue_size) this function checks -// whether histo_queue[queue_size] should be accepted and swaps it with the -// front if it is smaller. Otherwise, it leaves it as is. -static void UpdateQueueFront(HistoQueue* const histo_queue) { - if (histo_queue->queue[histo_queue->size].cost_diff >= 0) return; - - if (histo_queue->queue[histo_queue->size].cost_diff < - histo_queue->queue[0].cost_diff) { - SwapHistogramPairs(histo_queue->queue, - histo_queue->queue + histo_queue->size); +// Check whether a pair in the queue should be updated as head or not. +static void HistoQueueUpdateHead(HistoQueue* const histo_queue, + HistogramPair* const pair) { + assert(pair->cost_diff < 0.); + assert(pair >= histo_queue->queue && + pair < (histo_queue->queue + histo_queue->size)); + assert(histo_queue->size > 0); + if (pair->cost_diff < histo_queue->queue[0].cost_diff) { + // Replace the best pair. + const HistogramPair tmp = histo_queue->queue[0]; + histo_queue->queue[0] = *pair; + *pair = tmp; } - ++histo_queue->size; - - // We cannot add more elements than the capacity. - // The allocation adds an extra element to the official capacity so that - // histo_queue->queue[histo_queue->max_size] is read/written within bound. - assert(histo_queue->size <= histo_queue->max_size); } -// ----------------------------------------------------------------------------- - -static void PreparePair(VP8LHistogram** histograms, int idx1, int idx2, - HistogramPair* const pair) { - VP8LHistogram* h1; - VP8LHistogram* h2; +// Create a pair from indices "idx1" and "idx2" provided its cost +// is inferior to "threshold", a negative entropy. +// It returns the cost of the pair, or 0. if it superior to threshold. +static double HistoQueuePush(HistoQueue* const histo_queue, + VP8LHistogram** const histograms, int idx1, + int idx2, double threshold) { + const VP8LHistogram* h1; + const VP8LHistogram* h2; + HistogramPair pair; double sum_cost; + assert(threshold <= 0.); if (idx1 > idx2) { const int tmp = idx2; idx2 = idx1; idx1 = tmp; } - pair->idx1 = idx1; - pair->idx2 = idx2; + pair.idx1 = idx1; + pair.idx2 = idx2; h1 = histograms[idx1]; h2 = histograms[idx2]; sum_cost = h1->bit_cost_ + h2->bit_cost_; - pair->cost_combo = 0.; - GetCombinedHistogramEntropy(h1, h2, sum_cost, &pair->cost_combo); - pair->cost_diff = pair->cost_combo - sum_cost; + pair.cost_combo = 0.; + GetCombinedHistogramEntropy(h1, h2, sum_cost + threshold, &pair.cost_combo); + pair.cost_diff = pair.cost_combo - sum_cost; + + // Do not even consider the pair if it does not improve the entropy. + if (pair.cost_diff >= threshold) return 0.; + + // We cannot add more elements than the capacity. + assert(histo_queue->size < histo_queue->max_size); + histo_queue->queue[histo_queue->size++] = pair; + HistoQueueUpdateHead(histo_queue, &histo_queue->queue[histo_queue->size - 1]); + + return pair.cost_diff; } +// ----------------------------------------------------------------------------- + // Combines histograms by continuously choosing the one with the highest cost // reduction. static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) { @@ -714,13 +740,11 @@ static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) { clusters[i] = i; for (j = i + 1; j < image_histo_size; ++j) { // Initialize positions array. - PreparePair(histograms, i, j, &histo_queue.queue[histo_queue.size]); - UpdateQueueFront(&histo_queue); + HistoQueuePush(&histo_queue, histograms, i, j, 0.); } } while (image_histo_size > 1 && histo_queue.size > 0) { - HistogramPair* copy_to; const int idx1 = histo_queue.queue[0].idx1; const int idx2 = histo_queue.queue[0].idx2; HistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]); @@ -733,31 +757,22 @@ static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) { } --image_histo_size; - // Remove pairs intersecting the just combined best pair. This will - // therefore pop the head of the queue. - copy_to = histo_queue.queue; - for (i = 0; i < histo_queue.size; ++i) { + // Remove pairs intersecting the just combined best pair. + for (i = 0; i < histo_queue.size;) { HistogramPair* const p = histo_queue.queue + i; if (p->idx1 == idx1 || p->idx2 == idx1 || p->idx1 == idx2 || p->idx2 == idx2) { - // Do not copy the invalid pair. - continue; + HistoQueuePopPair(&histo_queue, p); + } else { + HistoQueueUpdateHead(&histo_queue, p); + ++i; } - if (p->cost_diff < histo_queue.queue[0].cost_diff) { - // Replace the top of the queue if we found better. - SwapHistogramPairs(histo_queue.queue, p); - } - SwapHistogramPairs(copy_to, p); - ++copy_to; } - histo_queue.size = (int)(copy_to - histo_queue.queue); // Push new pairs formed with combined histogram to the queue. for (i = 0; i < image_histo_size; ++i) { if (clusters[i] != idx1) { - PreparePair(histograms, idx1, clusters[i], - &histo_queue.queue[histo_queue.size]); - UpdateQueueFront(&histo_queue); + HistoQueuePush(&histo_queue, histograms, idx1, clusters[i], 0.); } } } @@ -777,90 +792,130 @@ static int HistogramCombineGreedy(VP8LHistogramSet* const image_histo) { return ok; } -static void HistogramCombineStochastic(VP8LHistogramSet* const image_histo, - VP8LHistogram* tmp_histo, - VP8LHistogram* best_combo, - int quality, int min_cluster_size) { +// Perform histogram aggregation using a stochastic approach. +// 'do_greedy' is set to 1 if a greedy approach needs to be performed +// afterwards, 0 otherwise. +static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo, + int min_cluster_size, + int* const do_greedy) { int iter; - uint32_t seed = 0; + uint32_t seed = 1; int tries_with_no_success = 0; int image_histo_size = image_histo->size; - const int iter_mult = (quality < 25) ? 2 : 2 + (quality - 25) / 8; - const int outer_iters = image_histo_size * iter_mult; - const int num_pairs = image_histo_size / 2; + const int outer_iters = image_histo_size; const int num_tries_no_success = outer_iters / 2; - int idx2_max = image_histo_size - 1; - int do_brute_dorce = 0; VP8LHistogram** const histograms = image_histo->histograms; + // Priority queue of histogram pairs. Its size of "kCostHeapSizeSqrt"^2 + // impacts the quality of the compression and the speed: the smaller the + // faster but the worse for the compression. + HistoQueue histo_queue; + const int kHistoQueueSizeSqrt = 3; + int ok = 0; + if (!HistoQueueInit(&histo_queue, kHistoQueueSizeSqrt)) { + goto End; + } // Collapse similar histograms in 'image_histo'. ++min_cluster_size; - for (iter = 0; - iter < outer_iters && image_histo_size >= min_cluster_size; + for (iter = 0; iter < outer_iters && image_histo_size >= min_cluster_size && + ++tries_with_no_success < num_tries_no_success; ++iter) { - double best_cost_diff = 0.; + double best_cost = + (histo_queue.size == 0) ? 0. : histo_queue.queue[0].cost_diff; int best_idx1 = -1, best_idx2 = 1; int j; - int num_tries = - (num_pairs < image_histo_size) ? num_pairs : image_histo_size; - // Use a brute force approach if: - // - stochastic has not worked for a while and - // - if the number of iterations for brute force is less than the number of - // iterations if we never find a match ever again stochastically (hence - // num_tries times the number of remaining outer iterations). - do_brute_dorce = - (tries_with_no_success > 10) && - (idx2_max * (idx2_max + 1) < 2 * num_tries * (outer_iters - iter)); - if (do_brute_dorce) num_tries = idx2_max; + const uint32_t rand_range = (image_histo_size - 1) * image_histo_size; + // image_histo_size / 2 was chosen empirically. Less means faster but worse + // compression. + const int num_tries = image_histo_size / 2; - seed += iter; for (j = 0; j < num_tries; ++j) { - double curr_cost_diff; - // Choose two histograms at random and try to combine them. - uint32_t idx1, idx2; - if (do_brute_dorce) { - // Use a brute force approach. - idx1 = (uint32_t)j; - idx2 = (uint32_t)idx2_max; - } else { - const uint32_t tmp = (j & 7) + 1; - const uint32_t diff = - (tmp < 3) ? tmp : MyRand(&seed) % (image_histo_size - 1); - idx1 = MyRand(&seed) % image_histo_size; - idx2 = (idx1 + diff + 1) % image_histo_size; - if (idx1 == idx2) { + double curr_cost; + // Choose two different histograms at random and try to combine them. + const uint32_t tmp = MyRand(&seed) % rand_range; + const uint32_t idx1 = tmp / (image_histo_size - 1); + uint32_t idx2 = tmp % (image_histo_size - 1); + if (idx2 >= idx1) ++idx2; + + // Calculate cost reduction on combination. + curr_cost = + HistoQueuePush(&histo_queue, histograms, idx1, idx2, best_cost); + if (curr_cost < 0) { // found a better pair? + best_cost = curr_cost; + // Empty the queue if we reached full capacity. + if (histo_queue.size == histo_queue.max_size) break; + } + } + if (histo_queue.size == 0) continue; + + // Merge the two best histograms. + best_idx1 = histo_queue.queue[0].idx1; + best_idx2 = histo_queue.queue[0].idx2; + assert(best_idx1 < best_idx2); + HistogramAddEval(histograms[best_idx1], histograms[best_idx2], + histograms[best_idx1], 0); + // Swap the best_idx2 histogram with the last one (which is now unused). + --image_histo_size; + if (best_idx2 != image_histo_size) { + HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]); + } + histograms[image_histo_size] = NULL; + // Parse the queue and update each pair that deals with best_idx1, + // best_idx2 or image_histo_size. + for (j = 0; j < histo_queue.size;) { + HistogramPair* const p = histo_queue.queue + j; + const int is_idx1_best = p->idx1 == best_idx1 || p->idx1 == best_idx2; + const int is_idx2_best = p->idx2 == best_idx1 || p->idx2 == best_idx2; + int do_eval = 0; + // The front pair could have been duplicated by a random pick so + // check for it all the time nevertheless. + if (is_idx1_best && is_idx2_best) { + HistoQueuePopPair(&histo_queue, p); + continue; + } + // Any pair containing one of the two best indices should only refer to + // best_idx1. Its cost should also be updated. + if (is_idx1_best) { + p->idx1 = best_idx1; + do_eval = 1; + } else if (is_idx2_best) { + p->idx2 = best_idx1; + do_eval = 1; + } + if (p->idx2 == image_histo_size) { + // No need to re-evaluate here as it does not involve a pair + // containing best_idx1 or best_idx2. + p->idx2 = best_idx2; + } + assert(p->idx2 < image_histo_size); + // Make sure the index order is respected. + if (p->idx1 > p->idx2) { + const int tmp = p->idx2; + p->idx2 = p->idx1; + p->idx1 = tmp; + } + if (do_eval) { + // Re-evaluate the cost of an updated pair. + GetCombinedHistogramEntropy(histograms[p->idx1], histograms[p->idx2], 0, + &p->cost_diff); + if (p->cost_diff >= 0.) { + HistoQueuePopPair(&histo_queue, p); continue; } } + HistoQueueUpdateHead(&histo_queue, p); + ++j; + } - // Calculate cost reduction on combining. - curr_cost_diff = HistogramAddEval(histograms[idx1], histograms[idx2], - tmp_histo, best_cost_diff); - if (curr_cost_diff < best_cost_diff) { // found a better pair? - HistogramSwap(&best_combo, &tmp_histo); - best_cost_diff = curr_cost_diff; - best_idx1 = idx1; - best_idx2 = idx2; - } - } - if (do_brute_dorce) --idx2_max; - - if (best_idx1 >= 0) { - HistogramSwap(&best_combo, &histograms[best_idx1]); - // swap best_idx2 slot with last one (which is now unused) - --image_histo_size; - if (idx2_max >= image_histo_size) idx2_max = image_histo_size - 1; - if (best_idx2 != image_histo_size) { - HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]); - histograms[image_histo_size] = NULL; - } - tries_with_no_success = 0; - } - if (++tries_with_no_success >= num_tries_no_success || idx2_max == 0) { - break; - } + tries_with_no_success = 0; } image_histo->size = image_histo_size; + *do_greedy = (image_histo->size <= min_cluster_size); + ok = 1; + +End: + HistoQueueClear(&histo_queue); + return ok; } // ----------------------------------------------------------------------------- @@ -925,7 +980,7 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize, int quality, int low_effort, int histo_bits, int cache_bits, VP8LHistogramSet* const image_histo, - VP8LHistogramSet* const tmp_histos, + VP8LHistogram* const tmp_histo, uint16_t* const histogram_symbols) { int ok = 0; const int histo_xsize = histo_bits ? VP8LSubSampleSize(xsize, histo_bits) : 1; @@ -933,7 +988,6 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize, const int image_histo_raw_size = histo_xsize * histo_ysize; VP8LHistogramSet* const orig_histo = VP8LAllocateHistogramSet(image_histo_raw_size, cache_bits); - VP8LHistogram* cur_combo; // Don't attempt linear bin-partition heuristic for // histograms of small sizes (as bin_map will be very sparse) and // maximum quality q==100 (to preserve the compression gains at that level). @@ -948,7 +1002,6 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize, // Copies the histograms and computes its bit_cost. HistogramCopyAndAnalyze(orig_histo, image_histo); - cur_combo = tmp_histos->histograms[1]; // pick up working slot if (entropy_combine) { const int bin_map_size = orig_histo->size; // Reuse histogram_symbols storage. By definition, it's guaranteed to be ok. @@ -958,10 +1011,9 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize, HistogramAnalyzeEntropyBin(orig_histo, bin_map, low_effort); // Collapse histograms with similar entropy. - cur_combo = HistogramCombineEntropyBin(image_histo, cur_combo, - bin_map, bin_map_size, - entropy_combine_num_bins, - combine_cost_factor, low_effort); + HistogramCombineEntropyBin(image_histo, tmp_histo, bin_map, bin_map_size, + entropy_combine_num_bins, combine_cost_factor, + low_effort); } // Don't combine the histograms using stochastic and greedy heuristics for @@ -970,10 +1022,11 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize, const float x = quality / 100.f; // cubic ramp between 1 and MAX_HISTO_GREEDY: const int threshold_size = (int)(1 + (x * x * x) * (MAX_HISTO_GREEDY - 1)); - HistogramCombineStochastic(image_histo, tmp_histos->histograms[0], - cur_combo, quality, threshold_size); - if ((image_histo->size <= threshold_size) && - !HistogramCombineGreedy(image_histo)) { + int do_greedy; + if (!HistogramCombineStochastic(image_histo, threshold_size, &do_greedy)) { + goto Error; + } + if (do_greedy && !HistogramCombineGreedy(image_histo)) { goto Error; } } diff --git a/3rdparty/libwebp/enc/histogram_enc.h b/3rdparty/libwebp/src/enc/histogram_enc.h similarity index 90% rename from 3rdparty/libwebp/enc/histogram_enc.h rename to 3rdparty/libwebp/src/enc/histogram_enc.h index a9d258a166..15b1fbda34 100644 --- a/3rdparty/libwebp/enc/histogram_enc.h +++ b/3rdparty/libwebp/src/enc/histogram_enc.h @@ -11,14 +11,14 @@ // // Models the histograms of literal and distance codes. -#ifndef WEBP_ENC_HISTOGRAM_H_ -#define WEBP_ENC_HISTOGRAM_H_ +#ifndef WEBP_ENC_HISTOGRAM_ENC_H_ +#define WEBP_ENC_HISTOGRAM_ENC_H_ #include -#include "./backward_references_enc.h" -#include "../webp/format_constants.h" -#include "../webp/types.h" +#include "src/enc/backward_references_enc.h" +#include "src/webp/format_constants.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -90,7 +90,9 @@ VP8LHistogram* VP8LAllocateHistogram(int cache_bits); // Accumulate a token 'v' into a histogram. void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const histo, - const PixOrCopy* const v); + const PixOrCopy* const v, + int (*const distance_modifier)(int, int), + int distance_modifier_arg0); static WEBP_INLINE int VP8LHistogramNumCodes(int palette_code_bits) { return NUM_LITERAL_CODES + NUM_LENGTH_CODES + @@ -103,7 +105,7 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize, int quality, int low_effort, int histogram_bits, int cache_bits, VP8LHistogramSet* const image_in, - VP8LHistogramSet* const tmp_histos, + VP8LHistogram* const tmp_histo, uint16_t* const histogram_symbols); // Returns the entropy for the symbols in the input array. @@ -120,4 +122,4 @@ double VP8LHistogramEstimateBits(const VP8LHistogram* const p); } #endif -#endif // WEBP_ENC_HISTOGRAM_H_ +#endif // WEBP_ENC_HISTOGRAM_ENC_H_ diff --git a/3rdparty/libwebp/enc/iterator_enc.c b/3rdparty/libwebp/src/enc/iterator_enc.c similarity index 99% rename from 3rdparty/libwebp/enc/iterator_enc.c rename to 3rdparty/libwebp/src/enc/iterator_enc.c index e48d30bd31..cfacfd2401 100644 --- a/3rdparty/libwebp/enc/iterator_enc.c +++ b/3rdparty/libwebp/src/enc/iterator_enc.c @@ -13,7 +13,7 @@ #include -#include "./vp8i_enc.h" +#include "src/enc/vp8i_enc.h" //------------------------------------------------------------------------------ // VP8Iterator diff --git a/3rdparty/libwebp/enc/near_lossless_enc.c b/3rdparty/libwebp/src/enc/near_lossless_enc.c similarity index 58% rename from 3rdparty/libwebp/enc/near_lossless_enc.c rename to 3rdparty/libwebp/src/enc/near_lossless_enc.c index 2bd03ab20d..cadd14c664 100644 --- a/3rdparty/libwebp/enc/near_lossless_enc.c +++ b/3rdparty/libwebp/src/enc/near_lossless_enc.c @@ -17,18 +17,20 @@ #include #include -#include "../dsp/lossless_common.h" -#include "../utils/utils.h" -#include "./vp8i_enc.h" +#include "src/dsp/lossless_common.h" +#include "src/utils/utils.h" +#include "src/enc/vp8li_enc.h" + +#if (WEBP_NEAR_LOSSLESS == 1) #define MIN_DIM_FOR_NEAR_LOSSLESS 64 #define MAX_LIMIT_BITS 5 // Quantizes the value up or down to a multiple of 1<> 1) + ((a >> bits) & 1); +static uint32_t FindClosestDiscretized(uint32_t a, int bits) { + const uint32_t mask = (1u << bits) - 1; + const uint32_t biased = a + (mask >> 1) + ((a >> bits) & 1); assert(bits > 0); if (biased > 0xff) return 0xff; return biased & ~mask; @@ -69,22 +71,30 @@ static int IsSmooth(const uint32_t* const prev_row, } // Adjusts pixel values of image with given maximum error. -static void NearLossless(int xsize, int ysize, uint32_t* argb, - int limit_bits, uint32_t* copy_buffer) { +static void NearLossless(int xsize, int ysize, const uint32_t* argb_src, + int stride, int limit_bits, uint32_t* copy_buffer, + uint32_t* argb_dst) { int x, y; const int limit = 1 << limit_bits; uint32_t* prev_row = copy_buffer; uint32_t* curr_row = prev_row + xsize; uint32_t* next_row = curr_row + xsize; - memcpy(copy_buffer, argb, xsize * 2 * sizeof(argb[0])); + memcpy(curr_row, argb_src, xsize * sizeof(argb_src[0])); + memcpy(next_row, argb_src + stride, xsize * sizeof(argb_src[0])); - for (y = 1; y < ysize - 1; ++y) { - uint32_t* const curr_argb_row = argb + y * xsize; - uint32_t* const next_argb_row = curr_argb_row + xsize; - memcpy(next_row, next_argb_row, xsize * sizeof(argb[0])); - for (x = 1; x < xsize - 1; ++x) { - if (!IsSmooth(prev_row, curr_row, next_row, x, limit)) { - curr_argb_row[x] = ClosestDiscretizedArgb(curr_row[x], limit_bits); + for (y = 0; y < ysize; ++y, argb_src += stride, argb_dst += xsize) { + if (y == 0 || y == ysize - 1) { + memcpy(argb_dst, argb_src, xsize * sizeof(argb_src[0])); + } else { + memcpy(next_row, argb_src + stride, xsize * sizeof(argb_src[0])); + argb_dst[0] = argb_src[0]; + argb_dst[xsize - 1] = argb_src[xsize - 1]; + for (x = 1; x < xsize - 1; ++x) { + if (IsSmooth(prev_row, curr_row, next_row, x, limit)) { + argb_dst[x] = curr_row[x]; + } else { + argb_dst[x] = ClosestDiscretizedArgb(curr_row[x], limit_bits); + } } } { @@ -97,26 +107,45 @@ static void NearLossless(int xsize, int ysize, uint32_t* argb, } } -int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality) { +int VP8ApplyNearLossless(const WebPPicture* const picture, int quality, + uint32_t* const argb_dst) { int i; + const int xsize = picture->width; + const int ysize = picture->height; + const int stride = picture->argb_stride; uint32_t* const copy_buffer = (uint32_t*)WebPSafeMalloc(xsize * 3, sizeof(*copy_buffer)); const int limit_bits = VP8LNearLosslessBits(quality); - assert(argb != NULL); - assert(limit_bits >= 0); + assert(argb_dst != NULL); + assert(limit_bits > 0); assert(limit_bits <= MAX_LIMIT_BITS); if (copy_buffer == NULL) { return 0; } // For small icon images, don't attempt to apply near-lossless compression. - if (xsize < MIN_DIM_FOR_NEAR_LOSSLESS && ysize < MIN_DIM_FOR_NEAR_LOSSLESS) { + if ((xsize < MIN_DIM_FOR_NEAR_LOSSLESS && + ysize < MIN_DIM_FOR_NEAR_LOSSLESS) || + ysize < 3) { + for (i = 0; i < ysize; ++i) { + memcpy(argb_dst + i * xsize, picture->argb + i * picture->argb_stride, + xsize * sizeof(*argb_dst)); + } WebPSafeFree(copy_buffer); return 1; } - for (i = limit_bits; i != 0; --i) { - NearLossless(xsize, ysize, argb, i, copy_buffer); + NearLossless(xsize, ysize, picture->argb, stride, limit_bits, copy_buffer, + argb_dst); + for (i = limit_bits - 1; i != 0; --i) { + NearLossless(xsize, ysize, argb_dst, xsize, i, copy_buffer, argb_dst); } WebPSafeFree(copy_buffer); return 1; } +#else // (WEBP_NEAR_LOSSLESS == 1) + +// Define a stub to suppress compiler warnings. +extern void VP8LNearLosslessStub(void); +WEBP_TSAN_IGNORE_FUNCTION void VP8LNearLosslessStub(void) {} + +#endif // (WEBP_NEAR_LOSSLESS == 1) diff --git a/3rdparty/libwebp/enc/picture_csp_enc.c b/3rdparty/libwebp/src/enc/picture_csp_enc.c similarity index 96% rename from 3rdparty/libwebp/enc/picture_csp_enc.c rename to 3rdparty/libwebp/src/enc/picture_csp_enc.c index e5d1c75a66..d531dd0282 100644 --- a/3rdparty/libwebp/enc/picture_csp_enc.c +++ b/3rdparty/libwebp/src/enc/picture_csp_enc.c @@ -15,10 +15,12 @@ #include #include -#include "./vp8i_enc.h" -#include "../utils/random_utils.h" -#include "../utils/utils.h" -#include "../dsp/yuv.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/random_utils.h" +#include "src/utils/utils.h" +#include "src/dsp/dsp.h" +#include "src/dsp/lossless.h" +#include "src/dsp/yuv.h" // Uncomment to disable gamma-compression during RGB->U/V averaging #define USE_GAMMA_COMPRESSION @@ -39,12 +41,15 @@ static const union { static int CheckNonOpaque(const uint8_t* alpha, int width, int height, int x_step, int y_step) { if (alpha == NULL) return 0; - while (height-- > 0) { - int x; - for (x = 0; x < width * x_step; x += x_step) { - if (alpha[x] != 0xff) return 1; // TODO(skal): check 4/8 bytes at a time. + WebPInitAlphaProcessing(); + if (x_step == 1) { + for (; height-- > 0; alpha += y_step) { + if (WebPHasAlpha8b(alpha, width)) return 1; + } + } else { + for (; height-- > 0; alpha += y_step) { + if (WebPHasAlpha32b(alpha, width)) return 1; } - alpha += y_step; } return 0; } @@ -56,15 +61,10 @@ int WebPPictureHasTransparency(const WebPPicture* picture) { return CheckNonOpaque(picture->a, picture->width, picture->height, 1, picture->a_stride); } else { - int x, y; - const uint32_t* argb = picture->argb; - if (argb == NULL) return 0; - for (y = 0; y < picture->height; ++y) { - for (x = 0; x < picture->width; ++x) { - if (argb[x] < 0xff000000u) return 1; // test any alpha values != 0xff - } - argb += picture->argb_stride; - } + const int alpha_offset = ALPHA_IS_LAST ? 3 : 0; + return CheckNonOpaque((const uint8_t*)picture->argb + alpha_offset, + picture->width, picture->height, + 4, picture->argb_stride * sizeof(*picture->argb)); } return 0; } @@ -171,7 +171,7 @@ typedef uint16_t fixed_y_t; // unsigned type with extra SFIX precision for W #if defined(USE_GAMMA_COMPRESSION) // float variant of gamma-correction -// We use tables of different size and precision for the Rec709 +// We use tables of different size and precision for the Rec709 / BT2020 // transfer function. #define kGammaF (1./0.45) static float kGammaToLinearTabF[MAX_Y_T + 1]; // size scales with Y_FIX @@ -183,8 +183,8 @@ static WEBP_TSAN_IGNORE_FUNCTION void InitGammaTablesF(void) { int v; const double norm = 1. / MAX_Y_T; const double scale = 1. / kGammaTabSize; - const double a = 0.099; - const double thresh = 0.018; + const double a = 0.09929682680944; + const double thresh = 0.018053968510807; for (v = 0; v <= MAX_Y_T; ++v) { const double g = norm * v; if (g <= thresh * 4.5) { @@ -856,7 +856,6 @@ static int ImportYUVAFromRGBA(const uint8_t* r_ptr, return 0; } if (has_alpha) { - WebPInitAlphaProcessing(); assert(step == 4); #if defined(USE_GAMMA_COMPRESSION) && defined(USE_INVERSE_ALPHA_TABLE) assert(kAlphaFix + kGammaFix <= 31); @@ -1085,40 +1084,45 @@ int WebPPictureYUVAToARGB(WebPPicture* picture) { // automatic import / conversion static int Import(WebPPicture* const picture, - const uint8_t* const rgb, int rgb_stride, + const uint8_t* rgb, int rgb_stride, int step, int swap_rb, int import_alpha) { int y; const uint8_t* r_ptr = rgb + (swap_rb ? 2 : 0); const uint8_t* g_ptr = rgb + 1; const uint8_t* b_ptr = rgb + (swap_rb ? 0 : 2); - const uint8_t* a_ptr = import_alpha ? rgb + 3 : NULL; const int width = picture->width; const int height = picture->height; if (!picture->use_argb) { + const uint8_t* a_ptr = import_alpha ? rgb + 3 : NULL; return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride, 0.f /* no dithering */, 0, picture); } if (!WebPPictureAlloc(picture)) return 0; - VP8EncDspARGBInit(); + VP8LDspInit(); + WebPInitAlphaProcessing(); if (import_alpha) { uint32_t* dst = picture->argb; + const int do_copy = + (!swap_rb && !ALPHA_IS_LAST) || (swap_rb && ALPHA_IS_LAST); assert(step == 4); for (y = 0; y < height; ++y) { - VP8PackARGB(a_ptr, r_ptr, g_ptr, b_ptr, width, dst); - a_ptr += rgb_stride; - r_ptr += rgb_stride; - g_ptr += rgb_stride; - b_ptr += rgb_stride; + if (do_copy) { + memcpy(dst, rgb, width * 4); + } else { + // RGBA input order. Need to swap R and B. + VP8LConvertBGRAToRGBA((const uint32_t*)rgb, width, (uint8_t*)dst); + } + rgb += rgb_stride; dst += picture->argb_stride; } } else { uint32_t* dst = picture->argb; assert(step >= 3); for (y = 0; y < height; ++y) { - VP8PackRGB(r_ptr, g_ptr, b_ptr, width, step, dst); + WebPPackRGB(r_ptr, g_ptr, b_ptr, width, step, dst); r_ptr += rgb_stride; g_ptr += rgb_stride; b_ptr += rgb_stride; @@ -1130,12 +1134,7 @@ static int Import(WebPPicture* const picture, // Public API -int WebPPictureImportRGB(WebPPicture* picture, - const uint8_t* rgb, int rgb_stride) { - return (picture != NULL && rgb != NULL) - ? Import(picture, rgb, rgb_stride, 3, 0, 0) - : 0; -} +#if !defined(WEBP_REDUCE_CSP) int WebPPictureImportBGR(WebPPicture* picture, const uint8_t* rgb, int rgb_stride) { @@ -1144,13 +1143,6 @@ int WebPPictureImportBGR(WebPPicture* picture, : 0; } -int WebPPictureImportRGBA(WebPPicture* picture, - const uint8_t* rgba, int rgba_stride) { - return (picture != NULL && rgba != NULL) - ? Import(picture, rgba, rgba_stride, 4, 0, 1) - : 0; -} - int WebPPictureImportBGRA(WebPPicture* picture, const uint8_t* rgba, int rgba_stride) { return (picture != NULL && rgba != NULL) @@ -1158,12 +1150,6 @@ int WebPPictureImportBGRA(WebPPicture* picture, : 0; } -int WebPPictureImportRGBX(WebPPicture* picture, - const uint8_t* rgba, int rgba_stride) { - return (picture != NULL && rgba != NULL) - ? Import(picture, rgba, rgba_stride, 4, 0, 0) - : 0; -} int WebPPictureImportBGRX(WebPPicture* picture, const uint8_t* rgba, int rgba_stride) { @@ -1172,4 +1158,27 @@ int WebPPictureImportBGRX(WebPPicture* picture, : 0; } +#endif // WEBP_REDUCE_CSP + +int WebPPictureImportRGB(WebPPicture* picture, + const uint8_t* rgb, int rgb_stride) { + return (picture != NULL && rgb != NULL) + ? Import(picture, rgb, rgb_stride, 3, 0, 0) + : 0; +} + +int WebPPictureImportRGBA(WebPPicture* picture, + const uint8_t* rgba, int rgba_stride) { + return (picture != NULL && rgba != NULL) + ? Import(picture, rgba, rgba_stride, 4, 0, 1) + : 0; +} + +int WebPPictureImportRGBX(WebPPicture* picture, + const uint8_t* rgba, int rgba_stride) { + return (picture != NULL && rgba != NULL) + ? Import(picture, rgba, rgba_stride, 4, 0, 0) + : 0; +} + //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/enc/picture_enc.c b/3rdparty/libwebp/src/enc/picture_enc.c similarity index 93% rename from 3rdparty/libwebp/enc/picture_enc.c rename to 3rdparty/libwebp/src/enc/picture_enc.c index dfa66510fb..c691622d03 100644 --- a/3rdparty/libwebp/enc/picture_enc.c +++ b/3rdparty/libwebp/src/enc/picture_enc.c @@ -14,9 +14,9 @@ #include #include -#include "./vp8i_enc.h" -#include "../dsp/dsp.h" -#include "../utils/utils.h" +#include "src/enc/vp8i_enc.h" +#include "src/dsp/dsp.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // WebPPicture @@ -76,13 +76,12 @@ int WebPPictureAllocARGB(WebPPicture* const picture, int width, int height) { return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); } // allocate a new buffer. - memory = WebPSafeMalloc(argb_size, sizeof(*picture->argb)); + memory = WebPSafeMalloc(argb_size + WEBP_ALIGN_CST, sizeof(*picture->argb)); if (memory == NULL) { return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); } - // TODO(skal): align plane to cache line? picture->memory_argb_ = memory; - picture->argb = (uint32_t*)memory; + picture->argb = (uint32_t*)WEBP_ALIGN(memory); picture->argb_stride = width; return 1; } @@ -92,8 +91,8 @@ int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height) { (WebPEncCSP)((int)picture->colorspace & WEBP_CSP_UV_MASK); const int has_alpha = (int)picture->colorspace & WEBP_CSP_ALPHA_BIT; const int y_stride = width; - const int uv_width = (width + 1) >> 1; - const int uv_height = (height + 1) >> 1; + const int uv_width = (int)(((int64_t)width + 1) >> 1); + const int uv_height = (int)(((int64_t)height + 1) >> 1); const int uv_stride = uv_width; int a_width, a_stride; uint64_t y_size, uv_size, a_size, total_size; @@ -118,8 +117,8 @@ int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height) { total_size = y_size + a_size + 2 * uv_size; // Security and validation checks - if (width <= 0 || height <= 0 || // luma/alpha param error - uv_width < 0 || uv_height < 0) { // u/v param error + if (width <= 0 || height <= 0 || // luma/alpha param error + uv_width <= 0 || uv_height <= 0) { // u/v param error return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION); } // allocate a new buffer. @@ -271,9 +270,11 @@ size_t NAME(const uint8_t* in, int w, int h, int bps, float q, \ } ENCODE_FUNC(WebPEncodeRGB, WebPPictureImportRGB) -ENCODE_FUNC(WebPEncodeBGR, WebPPictureImportBGR) ENCODE_FUNC(WebPEncodeRGBA, WebPPictureImportRGBA) +#if !defined(WEBP_REDUCE_CSP) +ENCODE_FUNC(WebPEncodeBGR, WebPPictureImportBGR) ENCODE_FUNC(WebPEncodeBGRA, WebPPictureImportBGRA) +#endif // WEBP_REDUCE_CSP #undef ENCODE_FUNC @@ -284,9 +285,11 @@ size_t NAME(const uint8_t* in, int w, int h, int bps, uint8_t** out) { \ } LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGB, WebPPictureImportRGB) -LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGR, WebPPictureImportBGR) LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA) +#if !defined(WEBP_REDUCE_CSP) +LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGR, WebPPictureImportBGR) LOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA) +#endif // WEBP_REDUCE_CSP #undef LOSSLESS_ENCODE_FUNC diff --git a/3rdparty/libwebp/enc/picture_psnr_enc.c b/3rdparty/libwebp/src/enc/picture_psnr_enc.c similarity index 87% rename from 3rdparty/libwebp/enc/picture_psnr_enc.c rename to 3rdparty/libwebp/src/enc/picture_psnr_enc.c index 9c0b229507..362a7c79be 100644 --- a/3rdparty/libwebp/enc/picture_psnr_enc.c +++ b/3rdparty/libwebp/src/enc/picture_psnr_enc.c @@ -11,11 +11,15 @@ // // Author: Skal (pascal.massimino@gmail.com) +#include "src/webp/encode.h" + +#if !(defined(WEBP_DISABLE_STATS) || defined(WEBP_REDUCE_SIZE)) + #include #include -#include "./vp8i_enc.h" -#include "../utils/utils.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" typedef double (*AccumulateFunc)(const uint8_t* src, int src_stride, const uint8_t* ref, int ref_stride, @@ -210,4 +214,34 @@ int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref, return ok; } -//------------------------------------------------------------------------------ +#else // defined(WEBP_DISABLE_STATS) +int WebPPlaneDistortion(const uint8_t* src, size_t src_stride, + const uint8_t* ref, size_t ref_stride, + int width, int height, size_t x_step, + int type, float* distortion, float* result) { + (void)src; + (void)src_stride; + (void)ref; + (void)ref_stride; + (void)width; + (void)height; + (void)x_step; + (void)type; + if (distortion == NULL || result == NULL) return 0; + *distortion = 0.f; + *result = 0.f; + return 1; +} + +int WebPPictureDistortion(const WebPPicture* src, const WebPPicture* ref, + int type, float results[5]) { + int i; + (void)src; + (void)ref; + (void)type; + if (results == NULL) return 0; + for (i = 0; i < 5; ++i) results[i] = 0.f; + return 1; +} + +#endif // !defined(WEBP_DISABLE_STATS) diff --git a/3rdparty/libwebp/enc/picture_rescale_enc.c b/3rdparty/libwebp/src/enc/picture_rescale_enc.c similarity index 90% rename from 3rdparty/libwebp/enc/picture_rescale_enc.c rename to 3rdparty/libwebp/src/enc/picture_rescale_enc.c index 0b7181c0d7..58a6ae7b9d 100644 --- a/3rdparty/libwebp/enc/picture_rescale_enc.c +++ b/3rdparty/libwebp/src/enc/picture_rescale_enc.c @@ -11,12 +11,16 @@ // // Author: Skal (pascal.massimino@gmail.com) +#include "src/webp/encode.h" + +#if !defined(WEBP_REDUCE_SIZE) + #include #include -#include "./vp8i_enc.h" -#include "../utils/rescaler_utils.h" -#include "../utils/utils.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/rescaler_utils.h" +#include "src/utils/utils.h" #define HALVE(x) (((x) + 1) >> 1) @@ -261,4 +265,45 @@ int WebPPictureRescale(WebPPicture* pic, int width, int height) { return 1; } -//------------------------------------------------------------------------------ +#else // defined(WEBP_REDUCE_SIZE) + +int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) { + (void)src; + (void)dst; + return 0; +} + +int WebPPictureIsView(const WebPPicture* picture) { + (void)picture; + return 0; +} + +int WebPPictureView(const WebPPicture* src, + int left, int top, int width, int height, + WebPPicture* dst) { + (void)src; + (void)left; + (void)top; + (void)width; + (void)height; + (void)dst; + return 0; +} + +int WebPPictureCrop(WebPPicture* pic, + int left, int top, int width, int height) { + (void)pic; + (void)left; + (void)top; + (void)width; + (void)height; + return 0; +} + +int WebPPictureRescale(WebPPicture* pic, int width, int height) { + (void)pic; + (void)width; + (void)height; + return 0; +} +#endif // !defined(WEBP_REDUCE_SIZE) diff --git a/3rdparty/libwebp/enc/picture_tools_enc.c b/3rdparty/libwebp/src/enc/picture_tools_enc.c similarity index 64% rename from 3rdparty/libwebp/enc/picture_tools_enc.c rename to 3rdparty/libwebp/src/enc/picture_tools_enc.c index 895df51156..be292d4391 100644 --- a/3rdparty/libwebp/enc/picture_tools_enc.c +++ b/3rdparty/libwebp/src/enc/picture_tools_enc.c @@ -13,8 +13,8 @@ #include -#include "./vp8i_enc.h" -#include "../dsp/yuv.h" +#include "src/enc/vp8i_enc.h" +#include "src/dsp/yuv.h" static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) { return (0xff000000u | (r << 16) | (g << 8) | b); @@ -25,20 +25,7 @@ static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) { #define SIZE 8 #define SIZE2 (SIZE / 2) -static int is_transparent_area(const uint8_t* ptr, int stride, int size) { - int y, x; - for (y = 0; y < size; ++y) { - for (x = 0; x < size; ++x) { - if (ptr[x]) { - return 0; - } - } - ptr += stride; - } - return 1; -} - -static int is_transparent_argb_area(const uint32_t* ptr, int stride, int size) { +static int IsTransparentARGBArea(const uint32_t* ptr, int stride, int size) { int y, x; for (y = 0; y < size; ++y) { for (x = 0; x < size; ++x) { @@ -51,7 +38,7 @@ static int is_transparent_argb_area(const uint32_t* ptr, int stride, int size) { return 1; } -static void flatten(uint8_t* ptr, int v, int stride, int size) { +static void Flatten(uint8_t* ptr, int v, int stride, int size) { int y; for (y = 0; y < size; ++y) { memset(ptr, v, size); @@ -59,7 +46,7 @@ static void flatten(uint8_t* ptr, int v, int stride, int size) { } } -static void flatten_argb(uint32_t* ptr, uint32_t v, int stride, int size) { +static void FlattenARGB(uint32_t* ptr, uint32_t v, int stride, int size) { int x, y; for (y = 0; y < size; ++y) { for (x = 0; x < size; ++x) ptr[x] = v; @@ -67,54 +54,114 @@ static void flatten_argb(uint32_t* ptr, uint32_t v, int stride, int size) { } } +// Smoothen the luma components of transparent pixels. Return true if the whole +// block is transparent. +static int SmoothenBlock(const uint8_t* a_ptr, int a_stride, uint8_t* y_ptr, + int y_stride, int width, int height) { + int sum = 0, count = 0; + int x, y; + const uint8_t* alpha_ptr = a_ptr; + uint8_t* luma_ptr = y_ptr; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + if (alpha_ptr[x] != 0) { + ++count; + sum += luma_ptr[x]; + } + } + alpha_ptr += a_stride; + luma_ptr += y_stride; + } + if (count > 0 && count < width * height) { + const uint8_t avg_u8 = (uint8_t)(sum / count); + alpha_ptr = a_ptr; + luma_ptr = y_ptr; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + if (alpha_ptr[x] == 0) luma_ptr[x] = avg_u8; + } + alpha_ptr += a_stride; + luma_ptr += y_stride; + } + } + return (count == 0); +} + void WebPCleanupTransparentArea(WebPPicture* pic) { int x, y, w, h; if (pic == NULL) return; w = pic->width / SIZE; h = pic->height / SIZE; - // note: we ignore the left-overs on right/bottom + // note: we ignore the left-overs on right/bottom, except for SmoothenBlock(). if (pic->use_argb) { uint32_t argb_value = 0; for (y = 0; y < h; ++y) { int need_reset = 1; for (x = 0; x < w; ++x) { const int off = (y * pic->argb_stride + x) * SIZE; - if (is_transparent_argb_area(pic->argb + off, pic->argb_stride, SIZE)) { + if (IsTransparentARGBArea(pic->argb + off, pic->argb_stride, SIZE)) { if (need_reset) { argb_value = pic->argb[off]; need_reset = 0; } - flatten_argb(pic->argb + off, argb_value, pic->argb_stride, SIZE); + FlattenARGB(pic->argb + off, argb_value, pic->argb_stride, SIZE); } else { need_reset = 1; } } } } else { - const uint8_t* const a_ptr = pic->a; + const int width = pic->width; + const int height = pic->height; + const int y_stride = pic->y_stride; + const int uv_stride = pic->uv_stride; + const int a_stride = pic->a_stride; + uint8_t* y_ptr = pic->y; + uint8_t* u_ptr = pic->u; + uint8_t* v_ptr = pic->v; + const uint8_t* a_ptr = pic->a; int values[3] = { 0 }; - if (a_ptr == NULL) return; // nothing to do - for (y = 0; y < h; ++y) { + if (a_ptr == NULL || y_ptr == NULL || u_ptr == NULL || v_ptr == NULL) { + return; + } + for (y = 0; y + SIZE <= height; y += SIZE) { int need_reset = 1; - for (x = 0; x < w; ++x) { - const int off_a = (y * pic->a_stride + x) * SIZE; - const int off_y = (y * pic->y_stride + x) * SIZE; - const int off_uv = (y * pic->uv_stride + x) * SIZE2; - if (is_transparent_area(a_ptr + off_a, pic->a_stride, SIZE)) { + for (x = 0; x + SIZE <= width; x += SIZE) { + if (SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + SIZE, SIZE)) { if (need_reset) { - values[0] = pic->y[off_y]; - values[1] = pic->u[off_uv]; - values[2] = pic->v[off_uv]; + values[0] = y_ptr[x]; + values[1] = u_ptr[x >> 1]; + values[2] = v_ptr[x >> 1]; need_reset = 0; } - flatten(pic->y + off_y, values[0], pic->y_stride, SIZE); - flatten(pic->u + off_uv, values[1], pic->uv_stride, SIZE2); - flatten(pic->v + off_uv, values[2], pic->uv_stride, SIZE2); + Flatten(y_ptr + x, values[0], y_stride, SIZE); + Flatten(u_ptr + (x >> 1), values[1], uv_stride, SIZE2); + Flatten(v_ptr + (x >> 1), values[2], uv_stride, SIZE2); } else { need_reset = 1; } } + if (x < width) { + SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + width - x, SIZE); + } + a_ptr += SIZE * a_stride; + y_ptr += SIZE * y_stride; + u_ptr += SIZE2 * uv_stride; + v_ptr += SIZE2 * uv_stride; + } + if (y < height) { + const int sub_height = height - y; + for (x = 0; x + SIZE <= width; x += SIZE) { + SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + SIZE, sub_height); + } + if (x < width) { + SmoothenBlock(a_ptr + x, a_stride, y_ptr + x, y_stride, + width - x, sub_height); + } } } } @@ -144,9 +191,9 @@ void WebPCleanupTransparentAreaLossless(WebPPicture* const pic) { // Blend color and remove transparency info #define BLEND(V0, V1, ALPHA) \ - ((((V0) * (255 - (ALPHA)) + (V1) * (ALPHA)) * 0x101) >> 16) + ((((V0) * (255 - (ALPHA)) + (V1) * (ALPHA)) * 0x101 + 256) >> 16) #define BLEND_10BIT(V0, V1, ALPHA) \ - ((((V0) * (1020 - (ALPHA)) + (V1) * (ALPHA)) * 0x101) >> 18) + ((((V0) * (1020 - (ALPHA)) + (V1) * (ALPHA)) * 0x101 + 1024) >> 18) void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) { const int red = (background_rgb >> 16) & 0xff; diff --git a/3rdparty/libwebp/enc/predictor_enc.c b/3rdparty/libwebp/src/enc/predictor_enc.c similarity index 96% rename from 3rdparty/libwebp/enc/predictor_enc.c rename to 3rdparty/libwebp/src/enc/predictor_enc.c index 0639b74f1c..f3715f515e 100644 --- a/3rdparty/libwebp/enc/predictor_enc.c +++ b/3rdparty/libwebp/src/enc/predictor_enc.c @@ -14,9 +14,9 @@ // Urvang Joshi (urvang@google.com) // Vincent Rabaud (vrabaud@google.com) -#include "../dsp/lossless.h" -#include "../dsp/lossless_common.h" -#include "./vp8li_enc.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/enc/vp8li_enc.h" #define MAX_DIFF_COST (1e30f) @@ -26,7 +26,6 @@ static const uint32_t kMaskAlpha = 0xff000000; // Mostly used to reduce code size + readability static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; } -static WEBP_INLINE int GetMax(int a, int b) { return (a < b) ? b : a; } //------------------------------------------------------------------------------ // Methods to calculate Entropy (Shannon). @@ -90,6 +89,9 @@ static WEBP_INLINE void PredictBatch(int mode, int x_start, int y, } } +#if (WEBP_NEAR_LOSSLESS == 1) +static WEBP_INLINE int GetMax(int a, int b) { return (a < b) ? b : a; } + static int MaxDiffBetweenPixels(uint32_t p1, uint32_t p2) { const int diff_a = abs((int)(p1 >> 24) - (int)(p2 >> 24)); const int diff_r = abs((int)((p1 >> 16) & 0xff) - (int)((p2 >> 16) & 0xff)); @@ -180,6 +182,7 @@ static uint8_t NearLosslessComponent(uint8_t value, uint8_t predict, // max_quantization which is a power of 2, smaller than max_diff). Take care if // value and predict have undergone subtract green, which means that red and // blue are represented as offsets from green. +#define NEAR_LOSSLESS_DIFF(a, b) (uint8_t)((((int)(a) - (int)(b))) & 0xff) static uint32_t NearLossless(uint32_t value, uint32_t predict, int max_quantization, int max_diff, int used_subtract_green) { @@ -196,7 +199,7 @@ static uint32_t NearLossless(uint32_t value, uint32_t predict, } if ((value >> 24) == 0 || (value >> 24) == 0xff) { // Preserve transparency of fully transparent or fully opaque pixels. - a = ((value >> 24) - (predict >> 24)) & 0xff; + a = NEAR_LOSSLESS_DIFF(value >> 24, predict >> 24); } else { a = NearLosslessComponent(value >> 24, predict >> 24, 0xff, quantization); } @@ -209,15 +212,17 @@ static uint32_t NearLossless(uint32_t value, uint32_t predict, // The amount by which green has been adjusted during quantization. It is // subtracted from red and blue for compensation, to avoid accumulating two // quantization errors in them. - green_diff = (new_green - (value >> 8)) & 0xff; + green_diff = NEAR_LOSSLESS_DIFF(new_green, value >> 8); } - r = NearLosslessComponent(((value >> 16) - green_diff) & 0xff, + r = NearLosslessComponent(NEAR_LOSSLESS_DIFF(value >> 16, green_diff), (predict >> 16) & 0xff, 0xff - new_green, quantization); - b = NearLosslessComponent((value - green_diff) & 0xff, predict & 0xff, - 0xff - new_green, quantization); + b = NearLosslessComponent(NEAR_LOSSLESS_DIFF(value, green_diff), + predict & 0xff, 0xff - new_green, quantization); return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; } +#undef NEAR_LOSSLESS_DIFF +#endif // (WEBP_NEAR_LOSSLESS == 1) // Stores the difference between the pixel and its prediction in "out". // In case of a lossy encoding, updates the source image to avoid propagating @@ -244,6 +249,7 @@ static WEBP_INLINE void GetResidual( } else { predict = pred_func(current_row[x - 1], upper_row + x); } +#if (WEBP_NEAR_LOSSLESS == 1) if (max_quantization == 1 || mode == 0 || y == 0 || y == height - 1 || x == 0 || x == width - 1) { residual = VP8LSubPixels(current_row[x], predict); @@ -254,6 +260,13 @@ static WEBP_INLINE void GetResidual( current_row[x] = VP8LAddPixels(predict, residual); // x is never 0 here so we do not need to update upper_row like below. } +#else + (void)max_diffs; + (void)height; + (void)max_quantization; + (void)used_subtract_green; + residual = VP8LSubPixels(current_row[x], predict); +#endif if ((current_row[x] & kMaskAlpha) == 0) { // If alpha is 0, cleanup RGB. We can choose the RGB values of the // residual for best compression. The prediction of alpha itself can be @@ -296,11 +309,12 @@ static int GetBestPredictorForTile(int width, int height, const int max_x = GetMin(tile_size, width - start_x); // Whether there exist columns just outside the tile. const int have_left = (start_x > 0); - const int have_right = (max_x < width - start_x); // Position and size of the strip covering the tile and adjacent columns if // they exist. const int context_start_x = start_x - have_left; - const int context_width = max_x + have_left + have_right; +#if (WEBP_NEAR_LOSSLESS == 1) + const int context_width = max_x + have_left + (max_x < width - start_x); +#endif const int tiles_per_row = VP8LSubSampleSize(width, bits); // Prediction modes of the left and above neighbor tiles. const int left_mode = (tile_x > 0) ? @@ -352,10 +366,12 @@ static int GetBestPredictorForTile(int width, int height, memcpy(current_row + context_start_x, argb + y * width + context_start_x, sizeof(*argb) * (max_x + have_left + (y + 1 < height))); +#if (WEBP_NEAR_LOSSLESS == 1) if (max_quantization > 1 && y >= 1 && y + 1 < height) { MaxDiffsForRow(context_width, width, argb + y * width + context_start_x, max_diffs + context_start_x, used_subtract_green); } +#endif GetResidual(width, height, upper_row, current_row, max_diffs, mode, start_x, start_x + max_x, y, max_quantization, exact, @@ -405,7 +421,9 @@ static void CopyImageWithPrediction(int width, int height, uint32_t* upper_row = argb_scratch; uint32_t* current_row = upper_row + width + 1; uint8_t* current_max_diffs = (uint8_t*)(current_row + width + 1); +#if (WEBP_NEAR_LOSSLESS == 1) uint8_t* lower_max_diffs = current_max_diffs + width; +#endif int y; for (y = 0; y < height; ++y) { @@ -420,6 +438,7 @@ static void CopyImageWithPrediction(int width, int height, PredictBatch(kPredLowEffort, 0, y, width, current_row, upper_row, argb + y * width); } else { +#if (WEBP_NEAR_LOSSLESS == 1) if (max_quantization > 1) { // Compute max_diffs for the lower row now, because that needs the // contents of argb for the current row, which we will overwrite with @@ -432,6 +451,7 @@ static void CopyImageWithPrediction(int width, int height, used_subtract_green); } } +#endif for (x = 0; x < width;) { const int mode = (modes[(y >> bits) * tiles_per_row + (x >> bits)] >> 8) & 0xff; diff --git a/3rdparty/libwebp/enc/quant_enc.c b/3rdparty/libwebp/src/enc/quant_enc.c similarity index 99% rename from 3rdparty/libwebp/enc/quant_enc.c rename to 3rdparty/libwebp/src/enc/quant_enc.c index b118fb2a13..3b1a3129b5 100644 --- a/3rdparty/libwebp/enc/quant_enc.c +++ b/3rdparty/libwebp/src/enc/quant_enc.c @@ -15,8 +15,8 @@ #include #include // for abs() -#include "./vp8i_enc.h" -#include "./cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/cost_enc.h" #define DO_TRELLIS_I4 1 #define DO_TRELLIS_I16 1 // not a huge gain, but ok at low bitrate. @@ -457,11 +457,11 @@ void VP8SetSegmentParams(VP8Encoder* const enc, float quality) { // Form the predictions in cache // Must be ordered using {DC_PRED, TM_PRED, V_PRED, H_PRED} as index -const int VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 }; -const int VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 }; +const uint16_t VP8I16ModeOffsets[4] = { I16DC16, I16TM16, I16VE16, I16HE16 }; +const uint16_t VP8UVModeOffsets[4] = { C8DC8, C8TM8, C8VE8, C8HE8 }; // Must be indexed using {B_DC_PRED -> B_HU_PRED} as index -const int VP8I4ModeOffsets[NUM_BMODES] = { +const uint16_t VP8I4ModeOffsets[NUM_BMODES] = { I4DC4, I4TM4, I4VE4, I4HE4, I4RD4, I4VR4, I4LD4, I4VL4, I4HD4, I4HU4 }; @@ -492,14 +492,14 @@ void VP8MakeIntra4Preds(const VP8EncIterator* const it) { // |YYYY|....| 12 // +----+----+ -const int VP8Scan[16] = { // Luma +const uint16_t VP8Scan[16] = { // Luma 0 + 0 * BPS, 4 + 0 * BPS, 8 + 0 * BPS, 12 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, 8 + 4 * BPS, 12 + 4 * BPS, 0 + 8 * BPS, 4 + 8 * BPS, 8 + 8 * BPS, 12 + 8 * BPS, 0 + 12 * BPS, 4 + 12 * BPS, 8 + 12 * BPS, 12 + 12 * BPS, }; -static const int VP8ScanUV[4 + 4] = { +static const uint16_t VP8ScanUV[4 + 4] = { 0 + 0 * BPS, 4 + 0 * BPS, 0 + 4 * BPS, 4 + 4 * BPS, // U 8 + 0 * BPS, 12 + 0 * BPS, 8 + 4 * BPS, 12 + 4 * BPS // V }; @@ -1162,7 +1162,7 @@ static void RefineUsingDistortion(VP8EncIterator* const it, const uint8_t* const src = it->yuv_in_ + Y_OFF_ENC; for (mode = 0; mode < NUM_PRED_MODES; ++mode) { const uint8_t* const ref = it->yuv_p_ + VP8I16ModeOffsets[mode]; - const score_t score = VP8SSE16x16(src, ref) * RD_DISTO_MULT + const score_t score = (score_t)VP8SSE16x16(src, ref) * RD_DISTO_MULT + VP8FixedCostsI16[mode] * lambda_d_i16; if (mode > 0 && VP8FixedCostsI16[mode] > bit_limit) { continue; diff --git a/3rdparty/libwebp/enc/syntax_enc.c b/3rdparty/libwebp/src/enc/syntax_enc.c similarity index 97% rename from 3rdparty/libwebp/enc/syntax_enc.c rename to 3rdparty/libwebp/src/enc/syntax_enc.c index 90665bd7e5..a9e5a6cf0f 100644 --- a/3rdparty/libwebp/enc/syntax_enc.c +++ b/3rdparty/libwebp/src/enc/syntax_enc.c @@ -13,10 +13,10 @@ #include -#include "../utils/utils.h" -#include "../webp/format_constants.h" // RIFF constants -#include "../webp/mux_types.h" // ALPHA_FLAG -#include "./vp8i_enc.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" // RIFF constants +#include "src/webp/mux_types.h" // ALPHA_FLAG +#include "src/enc/vp8i_enc.h" //------------------------------------------------------------------------------ // Helper functions @@ -289,11 +289,17 @@ static int GeneratePartition0(VP8Encoder* const enc) { pos3 = VP8BitWriterPos(bw); +#if !defined(WEBP_DISABLE_STATS) if (enc->pic_->stats) { enc->pic_->stats->header_bytes[0] = (int)((pos2 - pos1 + 7) >> 3); enc->pic_->stats->header_bytes[1] = (int)((pos3 - pos2 + 7) >> 3); enc->pic_->stats->alpha_data_size = (int)enc->alpha_data_size_; } +#else + (void)pos1; + (void)pos2; + (void)pos3; +#endif if (bw->error_) { return WebPEncodingSetError(enc->pic_, VP8_ENC_ERROR_OUT_OF_MEMORY); } diff --git a/3rdparty/libwebp/enc/token_enc.c b/3rdparty/libwebp/src/enc/token_enc.c similarity index 88% rename from 3rdparty/libwebp/enc/token_enc.c rename to 3rdparty/libwebp/src/enc/token_enc.c index 02a0d72cc6..3a2192acac 100644 --- a/3rdparty/libwebp/enc/token_enc.c +++ b/3rdparty/libwebp/src/enc/token_enc.c @@ -20,9 +20,9 @@ #include #include -#include "./cost_enc.h" -#include "./vp8i_enc.h" -#include "../utils/utils.h" +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/utils/utils.h" #if !defined(DISABLE_TOKEN_BUFFER) @@ -194,39 +194,6 @@ int VP8RecordCoeffTokens(int ctx, const struct VP8Residual* const res, #undef TOKEN_ID -//------------------------------------------------------------------------------ -// This function works, but isn't currently used. Saved for later. - -#if 0 - -static void Record(int bit, proba_t* const stats) { - proba_t p = *stats; - if (p >= 0xffff0000u) { // an overflow is inbound. - p = ((p + 1u) >> 1) & 0x7fff7fffu; // -> divide the stats by 2. - } - // record bit count (lower 16 bits) and increment total count (upper 16 bits). - p += 0x00010000u + bit; - *stats = p; -} - -void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats) { - const VP8Tokens* p = b->pages_; - while (p != NULL) { - const int N = (p->next_ == NULL) ? b->left_ : 0; - int n = MAX_NUM_TOKEN; - const token_t* const tokens = TOKEN_DATA(p); - while (n-- > N) { - const token_t token = tokens[n]; - if (!(token & FIXED_PROBA_BIT)) { - Record((token >> 15) & 1, stats + (token & 0x3fffu)); - } - } - p = p->next_; - } -} - -#endif // 0 - //------------------------------------------------------------------------------ // Final coding pass, with known probabilities @@ -283,8 +250,9 @@ size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas) { #else // DISABLE_TOKEN_BUFFER -void VP8TBufferInit(VP8TBuffer* const b) { +void VP8TBufferInit(VP8TBuffer* const b, int page_size) { (void)b; + (void)page_size; } void VP8TBufferClear(VP8TBuffer* const b) { (void)b; diff --git a/3rdparty/libwebp/enc/tree_enc.c b/3rdparty/libwebp/src/enc/tree_enc.c similarity index 99% rename from 3rdparty/libwebp/enc/tree_enc.c rename to 3rdparty/libwebp/src/enc/tree_enc.c index 2c40fe7f3d..64ed28360b 100644 --- a/3rdparty/libwebp/enc/tree_enc.c +++ b/3rdparty/libwebp/src/enc/tree_enc.c @@ -11,7 +11,7 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./vp8i_enc.h" +#include "src/enc/vp8i_enc.h" //------------------------------------------------------------------------------ // Default probabilities diff --git a/3rdparty/libwebp/enc/vp8i_enc.h b/3rdparty/libwebp/src/enc/vp8i_enc.h similarity index 94% rename from 3rdparty/libwebp/enc/vp8i_enc.h rename to 3rdparty/libwebp/src/enc/vp8i_enc.h index 93c95ecbfb..3463491e9d 100644 --- a/3rdparty/libwebp/enc/vp8i_enc.h +++ b/3rdparty/libwebp/src/enc/vp8i_enc.h @@ -11,16 +11,16 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_ENC_VP8ENCI_H_ -#define WEBP_ENC_VP8ENCI_H_ +#ifndef WEBP_ENC_VP8I_ENC_H_ +#define WEBP_ENC_VP8I_ENC_H_ #include // for memcpy() -#include "../dec/common_dec.h" -#include "../dsp/dsp.h" -#include "../utils/bit_writer_utils.h" -#include "../utils/thread_utils.h" -#include "../utils/utils.h" -#include "../webp/encode.h" +#include "src/dec/common_dec.h" +#include "src/dsp/dsp.h" +#include "src/utils/bit_writer_utils.h" +#include "src/utils/thread_utils.h" +#include "src/utils/utils.h" +#include "src/webp/encode.h" #ifdef __cplusplus extern "C" { @@ -32,7 +32,7 @@ extern "C" { // version numbers #define ENC_MAJ_VERSION 0 #define ENC_MIN_VERSION 6 -#define ENC_REV_VERSION 0 +#define ENC_REV_VERSION 1 enum { MAX_LF_LEVELS = 64, // Maximum loop filter level MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost @@ -75,10 +75,10 @@ typedef enum { // Rate-distortion optimization levels #define U_OFF_ENC (16) #define V_OFF_ENC (16 + 8) -extern const int VP8Scan[16]; // in quant.c -extern const int VP8UVModeOffsets[4]; // in analyze.c -extern const int VP8I16ModeOffsets[4]; -extern const int VP8I4ModeOffsets[NUM_BMODES]; +extern const uint16_t VP8Scan[16]; +extern const uint16_t VP8UVModeOffsets[4]; +extern const uint16_t VP8I16ModeOffsets[4]; +extern const uint16_t VP8I4ModeOffsets[NUM_BMODES]; // Layout of prediction blocks // intra 16x16 @@ -330,9 +330,6 @@ int VP8RecordCoeffTokens(int ctx, const struct VP8Residual* const res, // Estimate the final coded size given a set of 'probas'. size_t VP8EstimateTokenSize(VP8TBuffer* const b, const uint8_t* const probas); -// unused for now -void VP8TokenToStats(const VP8TBuffer* const b, proba_t* const stats); - #endif // !DISABLE_TOKEN_BUFFER //------------------------------------------------------------------------------ @@ -502,19 +499,10 @@ int WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height); // compressibility (no guarantee, though). Assumes that pic->use_argb is true. void WebPCleanupTransparentAreaLossless(WebPPicture* const pic); - // in near_lossless.c -// Near lossless preprocessing in RGB color-space. -int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality); -// Near lossless adjustment for predictors. -void VP8ApplyNearLosslessPredict(int xsize, int ysize, int pred_bits, - const uint32_t* argb_orig, - uint32_t* argb, uint32_t* argb_scratch, - const uint32_t* const transform_data, - int quality, int subtract_green); //------------------------------------------------------------------------------ #ifdef __cplusplus } // extern "C" #endif -#endif /* WEBP_ENC_VP8ENCI_H_ */ +#endif /* WEBP_ENC_VP8I_ENC_H_ */ diff --git a/3rdparty/libwebp/enc/vp8l_enc.c b/3rdparty/libwebp/src/enc/vp8l_enc.c similarity index 66% rename from 3rdparty/libwebp/enc/vp8l_enc.c rename to 3rdparty/libwebp/src/enc/vp8l_enc.c index b1a793d956..312e521906 100644 --- a/3rdparty/libwebp/enc/vp8l_enc.c +++ b/3rdparty/libwebp/src/enc/vp8l_enc.c @@ -15,20 +15,19 @@ #include #include -#include "./backward_references_enc.h" -#include "./histogram_enc.h" -#include "./vp8i_enc.h" -#include "./vp8li_enc.h" -#include "../dsp/lossless.h" -#include "../dsp/lossless_common.h" -#include "../utils/bit_writer_utils.h" -#include "../utils/huffman_encode_utils.h" -#include "../utils/utils.h" -#include "../webp/format_constants.h" +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/vp8li_enc.h" +#include "src/dsp/lossless.h" +#include "src/dsp/lossless_common.h" +#include "src/utils/bit_writer_utils.h" +#include "src/utils/huffman_encode_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" -#include "./delta_palettization_enc.h" +#include "src/enc/delta_palettization_enc.h" -#define PALETTE_KEY_RIGHT_SHIFT 22 // Key for 1K buffer. // Maximum number of histogram images (sub-blocks). #define MAX_HUFF_IMAGE_SIZE 2600 @@ -128,7 +127,10 @@ static int AnalyzeAndCreatePalette(const WebPPicture* const pic, uint32_t palette[MAX_PALETTE_SIZE], int* const palette_size) { const int num_colors = WebPGetColorPalette(pic, palette); - if (num_colors > MAX_PALETTE_SIZE) return 0; + if (num_colors > MAX_PALETTE_SIZE) { + *palette_size = 0; + return 0; + } *palette_size = num_colors; qsort(palette, num_colors, sizeof(*palette), PaletteCompareColorsForQsort); if (!low_effort && PaletteHasNonMonotonousDeltas(palette, num_colors)) { @@ -188,22 +190,33 @@ static WEBP_INLINE uint32_t HashPix(uint32_t pix) { static int AnalyzeEntropy(const uint32_t* argb, int width, int height, int argb_stride, int use_palette, + int palette_size, int transform_bits, EntropyIx* const min_entropy_ix, int* const red_and_blue_always_zero) { // Allocate histogram set with cache_bits = 0. - uint32_t* const histo = - (uint32_t*)WebPSafeCalloc(kHistoTotal, sizeof(*histo) * 256); + uint32_t* histo; + + if (use_palette && palette_size <= 16) { + // In the case of small palettes, we pack 2, 4 or 8 pixels together. In + // practice, small palettes are better than any other transform. + *min_entropy_ix = kPalette; + *red_and_blue_always_zero = 1; + return 1; + } + histo = (uint32_t*)WebPSafeCalloc(kHistoTotal, sizeof(*histo) * 256); if (histo != NULL) { int i, x, y; - const uint32_t* prev_row = argb; - const uint32_t* curr_row = argb + argb_stride; - for (y = 1; y < height; ++y) { - uint32_t prev_pix = curr_row[0]; - for (x = 1; x < width; ++x) { + const uint32_t* prev_row = NULL; + const uint32_t* curr_row = argb; + uint32_t pix_prev = argb[0]; // Skip the first pixel. + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { const uint32_t pix = curr_row[x]; - const uint32_t pix_diff = VP8LSubPixels(pix, prev_pix); - if ((pix_diff == 0) || (pix == prev_row[x])) continue; - prev_pix = pix; + const uint32_t pix_diff = VP8LSubPixels(pix, pix_prev); + pix_prev = pix; + if ((pix_diff == 0) || (prev_row != NULL && pix == prev_row[x])) { + continue; + } AddSingle(pix, &histo[kHistoAlpha * 256], &histo[kHistoRed * 256], @@ -264,8 +277,24 @@ static int AnalyzeEntropy(const uint32_t* argb, entropy_comp[kHistoRedPredSubGreen] + entropy_comp[kHistoGreenPred] + entropy_comp[kHistoBluePredSubGreen]; - // Palette mode seems more efficient in a breakeven case. Bias with 1.0. - entropy[kPalette] = entropy_comp[kHistoPalette] - 1.0; + entropy[kPalette] = entropy_comp[kHistoPalette]; + + // When including transforms, there is an overhead in bits from + // storing them. This overhead is small but matters for small images. + // For spatial, there are 14 transformations. + entropy[kSpatial] += VP8LSubSampleSize(width, transform_bits) * + VP8LSubSampleSize(height, transform_bits) * + VP8LFastLog2(14); + // For color transforms: 24 as only 3 channels are considered in a + // ColorTransformElement. + entropy[kSpatialSubGreen] += VP8LSubSampleSize(width, transform_bits) * + VP8LSubSampleSize(height, transform_bits) * + VP8LFastLog2(24); + // For palettes, add the cost of storing the palette. + // We empirically estimate the cost of a compressed entry as 8 bits. + // The palette is differential-coded when compressed hence a much + // lower cost than sizeof(uint32_t)*8. + entropy[kPalette] += palette_size * 8; *min_entropy_ix = kDirect; for (k = kDirect + 1; k <= last_mode_to_analyze; ++k) { @@ -273,6 +302,7 @@ static int AnalyzeEntropy(const uint32_t* argb, *min_entropy_ix = (EntropyIx)k; } } + assert((int)*min_entropy_ix <= last_mode_to_analyze); *red_and_blue_always_zero = 1; // Let's check if the histogram of the chosen entropy mode has // non-zero red and blue values. If all are zero, we can later skip @@ -325,60 +355,95 @@ static int GetTransformBits(int method, int histo_bits) { return res; } -static int AnalyzeAndInit(VP8LEncoder* const enc) { +// Set of parameters to be used in each iteration of the cruncher. +#define CRUNCH_CONFIGS_LZ77_MAX 2 +typedef struct { + int entropy_idx_; + int lz77s_types_to_try_[CRUNCH_CONFIGS_LZ77_MAX]; + int lz77s_types_to_try_size_; +} CrunchConfig; + +#define CRUNCH_CONFIGS_MAX kNumEntropyIx + +static int EncoderAnalyze(VP8LEncoder* const enc, + CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX], + int* const crunch_configs_size, + int* const red_and_blue_always_zero) { const WebPPicture* const pic = enc->pic_; const int width = pic->width; const int height = pic->height; - const int pix_cnt = width * height; const WebPConfig* const config = enc->config_; const int method = config->method; const int low_effort = (config->method == 0); - // we round the block size up, so we're guaranteed to have - // at max MAX_REFS_BLOCK_PER_IMAGE blocks used: - int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1; + int i; + int use_palette; + int n_lz77s; assert(pic != NULL && pic->argb != NULL); - enc->use_cross_color_ = 0; - enc->use_predict_ = 0; - enc->use_subtract_green_ = 0; - enc->use_palette_ = + use_palette = AnalyzeAndCreatePalette(pic, low_effort, enc->palette_, &enc->palette_size_); // TODO(jyrki): replace the decision to be based on an actual estimate // of entropy, or even spatial variance of entropy. - enc->histo_bits_ = GetHistoBits(method, enc->use_palette_, + enc->histo_bits_ = GetHistoBits(method, use_palette, pic->width, pic->height); enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_); if (low_effort) { // AnalyzeEntropy is somewhat slow. - enc->use_predict_ = !enc->use_palette_; - enc->use_subtract_green_ = !enc->use_palette_; - enc->use_cross_color_ = 0; + crunch_configs[0].entropy_idx_ = use_palette ? kPalette : kSpatialSubGreen; + n_lz77s = 1; + *crunch_configs_size = 1; } else { - int red_and_blue_always_zero; EntropyIx min_entropy_ix; - if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, - enc->use_palette_, &min_entropy_ix, - &red_and_blue_always_zero)) { + // Try out multiple LZ77 on images with few colors. + n_lz77s = (enc->palette_size_ > 0 && enc->palette_size_ <= 16) ? 2 : 1; + if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, use_palette, + enc->palette_size_, enc->transform_bits_, + &min_entropy_ix, red_and_blue_always_zero)) { return 0; } - enc->use_palette_ = (min_entropy_ix == kPalette); - enc->use_subtract_green_ = - (min_entropy_ix == kSubGreen) || (min_entropy_ix == kSpatialSubGreen); - enc->use_predict_ = - (min_entropy_ix == kSpatial) || (min_entropy_ix == kSpatialSubGreen); - enc->use_cross_color_ = red_and_blue_always_zero ? 0 : enc->use_predict_; + if (method == 6 && config->quality == 100) { + // Go brute force on all transforms. + *crunch_configs_size = 0; + for (i = 0; i < kNumEntropyIx; ++i) { + if (i != kPalette || use_palette) { + assert(*crunch_configs_size < CRUNCH_CONFIGS_MAX); + crunch_configs[(*crunch_configs_size)++].entropy_idx_ = i; + } + } + } else { + // Only choose the guessed best transform. + *crunch_configs_size = 1; + crunch_configs[0].entropy_idx_ = min_entropy_ix; + } } + // Fill in the different LZ77s. + assert(n_lz77s <= CRUNCH_CONFIGS_LZ77_MAX); + for (i = 0; i < *crunch_configs_size; ++i) { + int j; + for (j = 0; j < n_lz77s; ++j) { + crunch_configs[i].lz77s_types_to_try_[j] = + (j == 0) ? kLZ77Standard | kLZ77RLE : kLZ77Box; + } + crunch_configs[i].lz77s_types_to_try_size_ = n_lz77s; + } + return 1; +} +static int EncoderInit(VP8LEncoder* const enc) { + const WebPPicture* const pic = enc->pic_; + const int width = pic->width; + const int height = pic->height; + const int pix_cnt = width * height; + // we round the block size up, so we're guaranteed to have + // at most MAX_REFS_BLOCK_PER_IMAGE blocks used: + const int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1; + int i; if (!VP8LHashChainInit(&enc->hash_chain_, pix_cnt)) return 0; - // palette-friendly input typically uses less literals - // -> reduce block size a bit - if (enc->use_palette_) refs_block_size /= 2; - VP8LBackwardRefsInit(&enc->refs_[0], refs_block_size); - VP8LBackwardRefsInit(&enc->refs_[1], refs_block_size); + for (i = 0; i < 3; ++i) VP8LBackwardRefsInit(&enc->refs_[i], refs_block_size); return 1; } @@ -571,11 +636,16 @@ static void StoreFullHuffmanCode(VP8LBitWriter* const bw, length = write_trimmed_length ? trimmed_length : num_tokens; VP8LPutBits(bw, write_trimmed_length, 1); if (write_trimmed_length) { - const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1); - const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2; - VP8LPutBits(bw, nbitpairs - 1, 3); - assert(trimmed_length >= 2); - VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2); + if (trimmed_length == 2) { + VP8LPutBits(bw, 0, 3 + 2); // nbitpairs=1, trimmed_length=2 + } else { + const int nbits = BitsLog2Floor(trimmed_length - 2); + const int nbitpairs = nbits / 2 + 1; + assert(trimmed_length > 2); + assert(nbitpairs - 1 < 8); + VP8LPutBits(bw, nbitpairs - 1, 3); + VP8LPutBits(bw, trimmed_length - 2, nbitpairs * 2); + } } StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code); } @@ -642,7 +712,7 @@ static WEBP_INLINE void WriteHuffmanCodeWithExtraBits( static WebPEncodingError StoreImageToBitMask( VP8LBitWriter* const bw, int width, int histo_bits, - VP8LBackwardRefs* const refs, + const VP8LBackwardRefs* const refs, const uint16_t* histogram_symbols, const HuffmanTreeCode* const huffman_codes) { const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1; @@ -665,7 +735,7 @@ static WebPEncodingError StoreImageToBitMask( codes = huffman_codes + 5 * histogram_ix; } if (PixOrCopyIsLiteral(v)) { - static const int order[] = { 1, 2, 0, 3 }; + static const uint8_t order[] = { 1, 2, 0, 3 }; int k; for (k = 0; k < 4; ++k) { const int code = PixOrCopyLiteral(v, order[k]); @@ -705,7 +775,8 @@ static WebPEncodingError StoreImageToBitMask( static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw, const uint32_t* const argb, VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2], + VP8LBackwardRefs* const refs_tmp1, + VP8LBackwardRefs* const refs_tmp2, int width, int height, int quality, int low_effort) { int i; @@ -730,8 +801,9 @@ static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw, err = VP8_ENC_ERROR_OUT_OF_MEMORY; goto Error; } - refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, &cache_bits, - hash_chain, refs_array); + refs = VP8LGetBackwardReferences(width, height, argb, quality, 0, + kLZ77Standard | kLZ77RLE, &cache_bits, + hash_chain, refs_tmp1, refs_tmp2); if (refs == NULL) { err = VP8_ENC_ERROR_OUT_OF_MEMORY; goto Error; @@ -788,39 +860,37 @@ static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw, return err; } -static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw, - const uint32_t* const argb, - VP8LHashChain* const hash_chain, - VP8LBackwardRefs refs_array[2], - int width, int height, int quality, - int low_effort, - int use_cache, int* cache_bits, - int histogram_bits, - size_t init_byte_position, - int* const hdr_size, - int* const data_size) { +static WebPEncodingError EncodeImageInternal( + VP8LBitWriter* const bw, const uint32_t* const argb, + VP8LHashChain* const hash_chain, VP8LBackwardRefs refs_array[3], int width, + int height, int quality, int low_effort, int use_cache, + const CrunchConfig* const config, int* cache_bits, int histogram_bits, + size_t init_byte_position, int* const hdr_size, int* const data_size) { WebPEncodingError err = VP8_ENC_OK; const uint32_t histogram_image_xysize = VP8LSubSampleSize(width, histogram_bits) * VP8LSubSampleSize(height, histogram_bits); VP8LHistogramSet* histogram_image = NULL; - VP8LHistogramSet* tmp_histos = NULL; + VP8LHistogram* tmp_histo = NULL; int histogram_image_size = 0; size_t bit_array_size = 0; - HuffmanTree* huff_tree = NULL; + HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc( + 3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree)); HuffmanTreeToken* tokens = NULL; HuffmanTreeCode* huffman_codes = NULL; - VP8LBackwardRefs refs; - VP8LBackwardRefs* best_refs; + VP8LBackwardRefs* refs_best; + VP8LBackwardRefs* refs_tmp; uint16_t* const histogram_symbols = (uint16_t*)WebPSafeMalloc(histogram_image_xysize, sizeof(*histogram_symbols)); + int lz77s_idx; + VP8LBitWriter bw_init = *bw, bw_best; + int hdr_size_tmp; assert(histogram_bits >= MIN_HUFFMAN_BITS); assert(histogram_bits <= MAX_HUFFMAN_BITS); assert(hdr_size != NULL); assert(data_size != NULL); - VP8LBackwardRefsInit(&refs, refs_array[0].block_size_); if (histogram_symbols == NULL) { err = VP8_ENC_ERROR_OUT_OF_MEMORY; goto Error; @@ -836,142 +906,162 @@ static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw, // 'best_refs' is the reference to the best backward refs and points to one // of refs_array[0] or refs_array[1]. // Calculate backward references from ARGB image. - if (!VP8LHashChainFill(hash_chain, quality, argb, width, height, - low_effort)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - best_refs = VP8LGetBackwardReferences(width, height, argb, quality, - low_effort, cache_bits, hash_chain, - refs_array); - if (best_refs == NULL || !VP8LBackwardRefsCopy(best_refs, &refs)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - histogram_image = - VP8LAllocateHistogramSet(histogram_image_xysize, *cache_bits); - tmp_histos = VP8LAllocateHistogramSet(2, *cache_bits); - if (histogram_image == NULL || tmp_histos == NULL) { + if (huff_tree == NULL || + !VP8LHashChainFill(hash_chain, quality, argb, width, height, + low_effort) || + !VP8LBitWriterInit(&bw_best, 0) || + (config->lz77s_types_to_try_size_ > 1 && + !VP8LBitWriterClone(bw, &bw_best))) { err = VP8_ENC_ERROR_OUT_OF_MEMORY; goto Error; } + for (lz77s_idx = 0; lz77s_idx < config->lz77s_types_to_try_size_; + ++lz77s_idx) { + refs_best = VP8LGetBackwardReferences( + width, height, argb, quality, low_effort, + config->lz77s_types_to_try_[lz77s_idx], cache_bits, hash_chain, + &refs_array[0], &refs_array[1]); + if (refs_best == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + // Keep the best references aside and use the other element from the first + // two as a temporary for later usage. + refs_tmp = &refs_array[refs_best == &refs_array[0] ? 1 : 0]; - // Build histogram image and symbols from backward references. - if (!VP8LGetHistoImageSymbols(width, height, &refs, quality, low_effort, - histogram_bits, *cache_bits, histogram_image, - tmp_histos, histogram_symbols)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Create Huffman bit lengths and codes for each histogram image. - histogram_image_size = histogram_image->size; - bit_array_size = 5 * histogram_image_size; - huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size, - sizeof(*huffman_codes)); - // Note: some histogram_image entries may point to tmp_histos[], so the latter - // need to outlive the following call to GetHuffBitLengthsAndCodes(). - if (huffman_codes == NULL || - !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Free combined histograms. - VP8LFreeHistogramSet(histogram_image); - histogram_image = NULL; + histogram_image = + VP8LAllocateHistogramSet(histogram_image_xysize, *cache_bits); + tmp_histo = VP8LAllocateHistogram(*cache_bits); + if (histogram_image == NULL || tmp_histo == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } - // Free scratch histograms. - VP8LFreeHistogramSet(tmp_histos); - tmp_histos = NULL; + // Build histogram image and symbols from backward references. + if (!VP8LGetHistoImageSymbols(width, height, refs_best, quality, low_effort, + histogram_bits, *cache_bits, histogram_image, + tmp_histo, histogram_symbols)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + // Create Huffman bit lengths and codes for each histogram image. + histogram_image_size = histogram_image->size; + bit_array_size = 5 * histogram_image_size; + huffman_codes = (HuffmanTreeCode*)WebPSafeCalloc(bit_array_size, + sizeof(*huffman_codes)); + // Note: some histogram_image entries may point to tmp_histos[], so the + // latter need to outlive the following call to GetHuffBitLengthsAndCodes(). + if (huffman_codes == NULL || + !GetHuffBitLengthsAndCodes(histogram_image, huffman_codes)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + // Free combined histograms. + VP8LFreeHistogramSet(histogram_image); + histogram_image = NULL; - // Color Cache parameters. - if (*cache_bits > 0) { - VP8LPutBits(bw, 1, 1); - VP8LPutBits(bw, *cache_bits, 4); - } else { - VP8LPutBits(bw, 0, 1); - } + // Free scratch histograms. + VP8LFreeHistogram(tmp_histo); + tmp_histo = NULL; - // Huffman image + meta huffman. - { - const int write_histogram_image = (histogram_image_size > 1); - VP8LPutBits(bw, write_histogram_image, 1); - if (write_histogram_image) { - uint32_t* const histogram_argb = - (uint32_t*)WebPSafeMalloc(histogram_image_xysize, - sizeof(*histogram_argb)); - int max_index = 0; - uint32_t i; - if (histogram_argb == NULL) { + // Color Cache parameters. + if (*cache_bits > 0) { + VP8LPutBits(bw, 1, 1); + VP8LPutBits(bw, *cache_bits, 4); + } else { + VP8LPutBits(bw, 0, 1); + } + + // Huffman image + meta huffman. + { + const int write_histogram_image = (histogram_image_size > 1); + VP8LPutBits(bw, write_histogram_image, 1); + if (write_histogram_image) { + uint32_t* const histogram_argb = + (uint32_t*)WebPSafeMalloc(histogram_image_xysize, + sizeof(*histogram_argb)); + int max_index = 0; + uint32_t i; + if (histogram_argb == NULL) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + for (i = 0; i < histogram_image_xysize; ++i) { + const int symbol_index = histogram_symbols[i] & 0xffff; + histogram_argb[i] = (symbol_index << 8); + if (symbol_index >= max_index) { + max_index = symbol_index + 1; + } + } + histogram_image_size = max_index; + + VP8LPutBits(bw, histogram_bits - 2, 3); + err = EncodeImageNoHuffman( + bw, histogram_argb, hash_chain, refs_tmp, &refs_array[2], + VP8LSubSampleSize(width, histogram_bits), + VP8LSubSampleSize(height, histogram_bits), quality, low_effort); + WebPSafeFree(histogram_argb); + if (err != VP8_ENC_OK) goto Error; + } + } + + // Store Huffman codes. + { + int i; + int max_tokens = 0; + // Find maximum number of symbols for the huffman tree-set. + for (i = 0; i < 5 * histogram_image_size; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + if (max_tokens < codes->num_symbols) { + max_tokens = codes->num_symbols; + } + } + tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, sizeof(*tokens)); + if (tokens == NULL) { err = VP8_ENC_ERROR_OUT_OF_MEMORY; goto Error; } - for (i = 0; i < histogram_image_xysize; ++i) { - const int symbol_index = histogram_symbols[i] & 0xffff; - histogram_argb[i] = (symbol_index << 8); - if (symbol_index >= max_index) { - max_index = symbol_index + 1; - } - } - histogram_image_size = max_index; - - VP8LPutBits(bw, histogram_bits - 2, 3); - err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array, - VP8LSubSampleSize(width, histogram_bits), - VP8LSubSampleSize(height, histogram_bits), - quality, low_effort); - WebPSafeFree(histogram_argb); - if (err != VP8_ENC_OK) goto Error; - } - } - - // Store Huffman codes. - { - int i; - int max_tokens = 0; - huff_tree = (HuffmanTree*)WebPSafeMalloc(3ULL * CODE_LENGTH_CODES, - sizeof(*huff_tree)); - if (huff_tree == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; - } - // Find maximum number of symbols for the huffman tree-set. - for (i = 0; i < 5 * histogram_image_size; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - if (max_tokens < codes->num_symbols) { - max_tokens = codes->num_symbols; + for (i = 0; i < 5 * histogram_image_size; ++i) { + HuffmanTreeCode* const codes = &huffman_codes[i]; + StoreHuffmanCode(bw, huff_tree, tokens, codes); + ClearHuffmanTreeIfOnlyOneSymbol(codes); } } - tokens = (HuffmanTreeToken*)WebPSafeMalloc(max_tokens, - sizeof(*tokens)); - if (tokens == NULL) { - err = VP8_ENC_ERROR_OUT_OF_MEMORY; - goto Error; + // Store actual literals. + hdr_size_tmp = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position); + err = StoreImageToBitMask(bw, width, histogram_bits, refs_best, + histogram_symbols, huffman_codes); + // Keep track of the smallest image so far. + if (lz77s_idx == 0 || + VP8LBitWriterNumBytes(bw) < VP8LBitWriterNumBytes(&bw_best)) { + *hdr_size = hdr_size_tmp; + *data_size = + (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size); + VP8LBitWriterSwap(bw, &bw_best); } - for (i = 0; i < 5 * histogram_image_size; ++i) { - HuffmanTreeCode* const codes = &huffman_codes[i]; - StoreHuffmanCode(bw, huff_tree, tokens, codes); - ClearHuffmanTreeIfOnlyOneSymbol(codes); + // Reset the bit writer for the following iteration if any. + if (config->lz77s_types_to_try_size_ > 1) VP8LBitWriterReset(&bw_init, bw); + WebPSafeFree(tokens); + tokens = NULL; + if (huffman_codes != NULL) { + WebPSafeFree(huffman_codes->codes); + WebPSafeFree(huffman_codes); + huffman_codes = NULL; } } - - *hdr_size = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position); - // Store actual literals. - err = StoreImageToBitMask(bw, width, histogram_bits, &refs, - histogram_symbols, huffman_codes); - *data_size = - (int)(VP8LBitWriterNumBytes(bw) - init_byte_position - *hdr_size); + VP8LBitWriterSwap(bw, &bw_best); Error: WebPSafeFree(tokens); WebPSafeFree(huff_tree); VP8LFreeHistogramSet(histogram_image); - VP8LFreeHistogramSet(tmp_histos); - VP8LBackwardRefsClear(&refs); + VP8LFreeHistogram(tmp_histo); if (huffman_codes != NULL) { WebPSafeFree(huffman_codes->codes); WebPSafeFree(huffman_codes); } WebPSafeFree(histogram_symbols); + VP8LBitWriterWipeOut(&bw_best); return err; } @@ -1005,11 +1095,11 @@ static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc, VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); assert(pred_bits >= 2); VP8LPutBits(bw, pred_bits - 2, 3); - return EncodeImageNoHuffman(bw, enc->transform_data_, - (VP8LHashChain*)&enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality, low_effort); + return EncodeImageNoHuffman( + bw, enc->transform_data_, (VP8LHashChain*)&enc->hash_chain_, + (VP8LBackwardRefs*)&enc->refs_[0], // cast const away + (VP8LBackwardRefs*)&enc->refs_[1], transform_width, transform_height, + quality, low_effort); } static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc, @@ -1026,11 +1116,11 @@ static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc, VP8LPutBits(bw, CROSS_COLOR_TRANSFORM, 2); assert(ccolor_transform_bits >= 2); VP8LPutBits(bw, ccolor_transform_bits - 2, 3); - return EncodeImageNoHuffman(bw, enc->transform_data_, - (VP8LHashChain*)&enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality, low_effort); + return EncodeImageNoHuffman( + bw, enc->transform_data_, (VP8LHashChain*)&enc->hash_chain_, + (VP8LBackwardRefs*)&enc->refs_[0], // cast const away + (VP8LBackwardRefs*)&enc->refs_[1], transform_width, transform_height, + quality, low_effort); } // ----------------------------------------------------------------------------- @@ -1144,6 +1234,7 @@ static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc, } enc->transform_mem_ = mem; enc->transform_mem_size_ = (size_t)mem_size; + enc->argb_content_ = kEncoderNone; } enc->argb_ = mem; mem = (uint32_t*)WEBP_ALIGN(mem + image_size); @@ -1164,11 +1255,13 @@ static WebPEncodingError MakeInputImageCopy(VP8LEncoder* const enc) { int y; err = AllocateTransformBuffer(enc, width, height); if (err != VP8_ENC_OK) return err; + if (enc->argb_content_ == kEncoderARGB) return VP8_ENC_OK; for (y = 0; y < height; ++y) { memcpy(enc->argb_ + y * width, picture->argb + y * picture->argb_stride, width * sizeof(*enc->argb_)); } + enc->argb_content_ = kEncoderARGB; assert(enc->current_width_ == width); return VP8_ENC_OK; } @@ -1215,12 +1308,13 @@ static WEBP_INLINE uint32_t ApplyPaletteHash0(uint32_t color) { static WEBP_INLINE uint32_t ApplyPaletteHash1(uint32_t color) { // Forget about alpha. - return ((color & 0x00ffffffu) * 4222244071u) >> (32 - PALETTE_INV_SIZE_BITS); + return ((uint32_t)((color & 0x00ffffffu) * 4222244071ull)) >> + (32 - PALETTE_INV_SIZE_BITS); } static WEBP_INLINE uint32_t ApplyPaletteHash2(uint32_t color) { // Forget about alpha. - return (color & 0x00ffffffu) * ((1u << 31) - 1) >> + return ((uint32_t)((color & 0x00ffffffu) * ((1ull << 31) - 1))) >> (32 - PALETTE_INV_SIZE_BITS); } @@ -1346,6 +1440,7 @@ static WebPEncodingError MapImageFromPalette(VP8LEncoder* const enc, err = ApplyPalette(src, src_stride, enc->argb_, enc->current_width_, palette, palette_size, width, height, xbits); + enc->argb_content_ = kEncoderPalette; return err; } @@ -1364,8 +1459,9 @@ static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, int low_effort, tmp_palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); } tmp_palette[0] = palette[0]; - return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, enc->refs_, - palette_size, 1, 20 /* quality */, low_effort); + return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, + &enc->refs_[0], &enc->refs_[1], palette_size, 1, + 20 /* quality */, low_effort); } #ifdef WEBP_EXPERIMENTAL_FEATURES @@ -1400,10 +1496,11 @@ static WebPEncodingError EncodeDeltaPalettePredictorImage( VP8LPutBits(bw, TRANSFORM_PRESENT, 1); VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2); VP8LPutBits(bw, pred_bits - 2, 3); - err = EncodeImageNoHuffman(bw, predictors, &enc->hash_chain_, - (VP8LBackwardRefs*)enc->refs_, // cast const away - transform_width, transform_height, - quality, low_effort); + err = EncodeImageNoHuffman( + bw, predictors, &enc->hash_chain_, + (VP8LBackwardRefs*)&enc->refs_[0], // cast const away + (VP8LBackwardRefs*)&enc->refs_[1], + transform_width, transform_height, quality, low_effort); WebPSafeFree(predictors); return err; } @@ -1422,6 +1519,7 @@ static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config, } enc->config_ = config; enc->pic_ = picture; + enc->argb_content_ = kEncoderNone; VP8LEncDspInit(); @@ -1430,9 +1528,9 @@ static VP8LEncoder* VP8LEncoderNew(const WebPConfig* const config, static void VP8LEncoderDelete(VP8LEncoder* enc) { if (enc != NULL) { + int i; VP8LHashChainClear(&enc->hash_chain_); - VP8LBackwardRefsClear(&enc->refs_[0]); - VP8LBackwardRefsClear(&enc->refs_[1]); + for (i = 0; i < 3; ++i) VP8LBackwardRefsClear(&enc->refs_[i]); ClearTransformBuffer(enc); WebPSafeFree(enc); } @@ -1441,134 +1539,347 @@ static void VP8LEncoderDelete(VP8LEncoder* enc) { // ----------------------------------------------------------------------------- // Main call -WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, - const WebPPicture* const picture, - VP8LBitWriter* const bw, int use_cache) { +typedef struct { + const WebPConfig* config_; + const WebPPicture* picture_; + VP8LBitWriter* bw_; + VP8LEncoder* enc_; + int use_cache_; + CrunchConfig crunch_configs_[CRUNCH_CONFIGS_MAX]; + int num_crunch_configs_; + int red_and_blue_always_zero_; + WebPEncodingError err_; + WebPAuxStats* stats_; +} StreamEncodeContext; + +static int EncodeStreamHook(void* input, void* data2) { + StreamEncodeContext* const params = (StreamEncodeContext*)input; + const WebPConfig* const config = params->config_; + const WebPPicture* const picture = params->picture_; + VP8LBitWriter* const bw = params->bw_; + VP8LEncoder* const enc = params->enc_; + const int use_cache = params->use_cache_; + const CrunchConfig* const crunch_configs = params->crunch_configs_; + const int num_crunch_configs = params->num_crunch_configs_; + const int red_and_blue_always_zero = params->red_and_blue_always_zero_; +#if !defined(WEBP_DISABLE_STATS) + WebPAuxStats* const stats = params->stats_; +#endif WebPEncodingError err = VP8_ENC_OK; const int quality = (int)config->quality; const int low_effort = (config->method == 0); +#if (WEBP_NEAR_LOSSLESS == 1) || defined(WEBP_EXPERIMENTAL_FEATURES) const int width = picture->width; +#endif const int height = picture->height; - VP8LEncoder* const enc = VP8LEncoderNew(config, picture); const size_t byte_position = VP8LBitWriterNumBytes(bw); +#if (WEBP_NEAR_LOSSLESS == 1) int use_near_lossless = 0; +#endif int hdr_size = 0; int data_size = 0; int use_delta_palette = 0; + int idx; + size_t best_size = 0; + VP8LBitWriter bw_init = *bw, bw_best; + (void)data2; - if (enc == NULL) { + if (!VP8LBitWriterInit(&bw_best, 0) || + (num_crunch_configs > 1 && !VP8LBitWriterClone(bw, &bw_best))) { err = VP8_ENC_ERROR_OUT_OF_MEMORY; goto Error; } - // --------------------------------------------------------------------------- + for (idx = 0; idx < num_crunch_configs; ++idx) { + const int entropy_idx = crunch_configs[idx].entropy_idx_; + enc->use_palette_ = (entropy_idx == kPalette); + enc->use_subtract_green_ = + (entropy_idx == kSubGreen) || (entropy_idx == kSpatialSubGreen); + enc->use_predict_ = + (entropy_idx == kSpatial) || (entropy_idx == kSpatialSubGreen); + if (low_effort) { + enc->use_cross_color_ = 0; + } else { + enc->use_cross_color_ = red_and_blue_always_zero ? 0 : enc->use_predict_; + } + // Reset any parameter in the encoder that is set in the previous iteration. + enc->cache_bits_ = 0; + VP8LBackwardRefsClear(&enc->refs_[0]); + VP8LBackwardRefsClear(&enc->refs_[1]); + +#if (WEBP_NEAR_LOSSLESS == 1) + // Apply near-lossless preprocessing. + use_near_lossless = (config->near_lossless < 100) && !enc->use_palette_ && + !enc->use_predict_; + if (use_near_lossless) { + err = AllocateTransformBuffer(enc, width, height); + if (err != VP8_ENC_OK) goto Error; + if ((enc->argb_content_ != kEncoderNearLossless) && + !VP8ApplyNearLossless(picture, config->near_lossless, enc->argb_)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + enc->argb_content_ = kEncoderNearLossless; + } else { + enc->argb_content_ = kEncoderNone; + } +#else + enc->argb_content_ = kEncoderNone; +#endif + +#ifdef WEBP_EXPERIMENTAL_FEATURES + if (config->use_delta_palette) { + enc->use_predict_ = 1; + enc->use_cross_color_ = 0; + enc->use_subtract_green_ = 0; + enc->use_palette_ = 1; + if (enc->argb_content_ != kEncoderNearLossless && + enc->argb_content_ != kEncoderPalette) { + err = MakeInputImageCopy(enc); + if (err != VP8_ENC_OK) goto Error; + } + err = WebPSearchOptimalDeltaPalette(enc); + if (err != VP8_ENC_OK) goto Error; + if (enc->use_palette_) { + err = AllocateTransformBuffer(enc, width, height); + if (err != VP8_ENC_OK) goto Error; + err = EncodeDeltaPalettePredictorImage(bw, enc, quality, low_effort); + if (err != VP8_ENC_OK) goto Error; + use_delta_palette = 1; + } + } +#endif // WEBP_EXPERIMENTAL_FEATURES + + // Encode palette + if (enc->use_palette_) { + err = EncodePalette(bw, low_effort, enc); + if (err != VP8_ENC_OK) goto Error; + err = MapImageFromPalette(enc, use_delta_palette); + if (err != VP8_ENC_OK) goto Error; + // If using a color cache, do not have it bigger than the number of + // colors. + if (use_cache && enc->palette_size_ < (1 << MAX_COLOR_CACHE_BITS)) { + enc->cache_bits_ = BitsLog2Floor(enc->palette_size_) + 1; + } + } + if (!use_delta_palette) { + // In case image is not packed. + if (enc->argb_content_ != kEncoderNearLossless && + enc->argb_content_ != kEncoderPalette) { + err = MakeInputImageCopy(enc); + if (err != VP8_ENC_OK) goto Error; + } + + // ----------------------------------------------------------------------- + // Apply transforms and write transform data. + + if (enc->use_subtract_green_) { + ApplySubtractGreen(enc, enc->current_width_, height, bw); + } + + if (enc->use_predict_) { + err = ApplyPredictFilter(enc, enc->current_width_, height, quality, + low_effort, enc->use_subtract_green_, bw); + if (err != VP8_ENC_OK) goto Error; + } + + if (enc->use_cross_color_) { + err = ApplyCrossColorFilter(enc, enc->current_width_, height, quality, + low_effort, bw); + if (err != VP8_ENC_OK) goto Error; + } + } + + VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms. + + // ------------------------------------------------------------------------- + // Encode and write the transformed image. + err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_, + enc->current_width_, height, quality, low_effort, + use_cache, &crunch_configs[idx], + &enc->cache_bits_, enc->histo_bits_, + byte_position, &hdr_size, &data_size); + if (err != VP8_ENC_OK) goto Error; + + // If we are better than what we already have. + if (idx == 0 || VP8LBitWriterNumBytes(bw) < best_size) { + best_size = VP8LBitWriterNumBytes(bw); + // Store the BitWriter. + VP8LBitWriterSwap(bw, &bw_best); +#if !defined(WEBP_DISABLE_STATS) + // Update the stats. + if (stats != NULL) { + stats->lossless_features = 0; + if (enc->use_predict_) stats->lossless_features |= 1; + if (enc->use_cross_color_) stats->lossless_features |= 2; + if (enc->use_subtract_green_) stats->lossless_features |= 4; + if (enc->use_palette_) stats->lossless_features |= 8; + stats->histogram_bits = enc->histo_bits_; + stats->transform_bits = enc->transform_bits_; + stats->cache_bits = enc->cache_bits_; + stats->palette_size = enc->palette_size_; + stats->lossless_size = (int)(best_size - byte_position); + stats->lossless_hdr_size = hdr_size; + stats->lossless_data_size = data_size; + } +#endif + } + // Reset the bit writer for the following iteration if any. + if (num_crunch_configs > 1) VP8LBitWriterReset(&bw_init, bw); + } + VP8LBitWriterSwap(&bw_best, bw); + +Error: + VP8LBitWriterWipeOut(&bw_best); + params->err_ = err; + // The hook should return false in case of error. + return (err == VP8_ENC_OK); +} + +WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, + const WebPPicture* const picture, + VP8LBitWriter* const bw_main, + int use_cache) { + WebPEncodingError err = VP8_ENC_OK; + VP8LEncoder* const enc_main = VP8LEncoderNew(config, picture); + VP8LEncoder* enc_side = NULL; + CrunchConfig crunch_configs[CRUNCH_CONFIGS_MAX]; + int num_crunch_configs_main, num_crunch_configs_side = 0; + int idx; + int red_and_blue_always_zero = 0; + WebPWorker worker_main, worker_side; + StreamEncodeContext params_main, params_side; + // The main thread uses picture->stats, the side thread uses stats_side. + WebPAuxStats stats_side; + VP8LBitWriter bw_side; + const WebPWorkerInterface* const worker_interface = WebPGetWorkerInterface(); + int ok_main; + // Analyze image (entropy, num_palettes etc) - - if (!AnalyzeAndInit(enc)) { + if (enc_main == NULL || + !EncoderAnalyze(enc_main, crunch_configs, &num_crunch_configs_main, + &red_and_blue_always_zero) || + !EncoderInit(enc_main) || !VP8LBitWriterInit(&bw_side, 0)) { err = VP8_ENC_ERROR_OUT_OF_MEMORY; goto Error; } - // Apply near-lossless preprocessing. - use_near_lossless = - (config->near_lossless < 100) && !enc->use_palette_ && !enc->use_predict_; - if (use_near_lossless) { - if (!VP8ApplyNearLossless(width, height, picture->argb, - config->near_lossless)) { + // Split the configs between the main and side threads (if any). + if (config->thread_level > 0) { + num_crunch_configs_side = num_crunch_configs_main / 2; + for (idx = 0; idx < num_crunch_configs_side; ++idx) { + params_side.crunch_configs_[idx] = + crunch_configs[num_crunch_configs_main - num_crunch_configs_side + + idx]; + } + params_side.num_crunch_configs_ = num_crunch_configs_side; + } + num_crunch_configs_main -= num_crunch_configs_side; + for (idx = 0; idx < num_crunch_configs_main; ++idx) { + params_main.crunch_configs_[idx] = crunch_configs[idx]; + } + params_main.num_crunch_configs_ = num_crunch_configs_main; + + // Fill in the parameters for the thread workers. + { + const int params_size = (num_crunch_configs_side > 0) ? 2 : 1; + for (idx = 0; idx < params_size; ++idx) { + // Create the parameters for each worker. + WebPWorker* const worker = (idx == 0) ? &worker_main : &worker_side; + StreamEncodeContext* const param = + (idx == 0) ? ¶ms_main : ¶ms_side; + param->config_ = config; + param->picture_ = picture; + param->use_cache_ = use_cache; + param->red_and_blue_always_zero_ = red_and_blue_always_zero; + if (idx == 0) { + param->stats_ = picture->stats; + param->bw_ = bw_main; + param->enc_ = enc_main; + } else { + param->stats_ = (picture->stats == NULL) ? NULL : &stats_side; + // Create a side bit writer. + if (!VP8LBitWriterClone(bw_main, &bw_side)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + param->bw_ = &bw_side; + // Create a side encoder. + enc_side = VP8LEncoderNew(config, picture); + if (enc_side == NULL || !EncoderInit(enc_side)) { + err = VP8_ENC_ERROR_OUT_OF_MEMORY; + goto Error; + } + // Copy the values that were computed for the main encoder. + enc_side->histo_bits_ = enc_main->histo_bits_; + enc_side->transform_bits_ = enc_main->transform_bits_; + enc_side->palette_size_ = enc_main->palette_size_; + memcpy(enc_side->palette_, enc_main->palette_, + sizeof(enc_main->palette_)); + param->enc_ = enc_side; + } + // Create the workers. + worker_interface->Init(worker); + worker->data1 = param; + worker->data2 = NULL; + worker->hook = (WebPWorkerHook)EncodeStreamHook; + } + } + + // Start the second thread if needed. + if (num_crunch_configs_side != 0) { + if (!worker_interface->Reset(&worker_side)) { err = VP8_ENC_ERROR_OUT_OF_MEMORY; goto Error; } +#if !defined(WEBP_DISABLE_STATS) + // This line is here and not in the param initialization above to remove a + // Clang static analyzer warning. + if (picture->stats != NULL) { + memcpy(&stats_side, picture->stats, sizeof(stats_side)); + } +#endif + // This line is only useful to remove a Clang static analyzer warning. + params_side.err_ = VP8_ENC_OK; + worker_interface->Launch(&worker_side); + } + // Execute the main thread. + worker_interface->Execute(&worker_main); + ok_main = worker_interface->Sync(&worker_main); + worker_interface->End(&worker_main); + if (num_crunch_configs_side != 0) { + // Wait for the second thread. + const int ok_side = worker_interface->Sync(&worker_side); + worker_interface->End(&worker_side); + if (!ok_main || !ok_side) { + err = ok_main ? params_side.err_ : params_main.err_; + goto Error; + } + if (VP8LBitWriterNumBytes(&bw_side) < VP8LBitWriterNumBytes(bw_main)) { + VP8LBitWriterSwap(bw_main, &bw_side); +#if !defined(WEBP_DISABLE_STATS) + if (picture->stats != NULL) { + memcpy(picture->stats, &stats_side, sizeof(*picture->stats)); + } +#endif + } + } else { + if (!ok_main) { + err = params_main.err_; + goto Error; + } } -#ifdef WEBP_EXPERIMENTAL_FEATURES - if (config->use_delta_palette) { - enc->use_predict_ = 1; - enc->use_cross_color_ = 0; - enc->use_subtract_green_ = 0; - enc->use_palette_ = 1; - err = MakeInputImageCopy(enc); - if (err != VP8_ENC_OK) goto Error; - err = WebPSearchOptimalDeltaPalette(enc); - if (err != VP8_ENC_OK) goto Error; - if (enc->use_palette_) { - err = AllocateTransformBuffer(enc, width, height); - if (err != VP8_ENC_OK) goto Error; - err = EncodeDeltaPalettePredictorImage(bw, enc, quality, low_effort); - if (err != VP8_ENC_OK) goto Error; - use_delta_palette = 1; - } - } -#endif // WEBP_EXPERIMENTAL_FEATURES - - // Encode palette - if (enc->use_palette_) { - err = EncodePalette(bw, low_effort, enc); - if (err != VP8_ENC_OK) goto Error; - err = MapImageFromPalette(enc, use_delta_palette); - if (err != VP8_ENC_OK) goto Error; - // If using a color cache, do not have it bigger than the number of colors. - if (use_cache && enc->palette_size_ < (1 << MAX_COLOR_CACHE_BITS)) { - enc->cache_bits_ = BitsLog2Floor(enc->palette_size_) + 1; - } - } - if (!use_delta_palette) { - // In case image is not packed. - if (enc->argb_ == NULL) { - err = MakeInputImageCopy(enc); - if (err != VP8_ENC_OK) goto Error; - } - - // ------------------------------------------------------------------------- - // Apply transforms and write transform data. - - if (enc->use_subtract_green_) { - ApplySubtractGreen(enc, enc->current_width_, height, bw); - } - - if (enc->use_predict_) { - err = ApplyPredictFilter(enc, enc->current_width_, height, quality, - low_effort, enc->use_subtract_green_, bw); - if (err != VP8_ENC_OK) goto Error; - } - - if (enc->use_cross_color_) { - err = ApplyCrossColorFilter(enc, enc->current_width_, - height, quality, low_effort, bw); - if (err != VP8_ENC_OK) goto Error; - } - } - - VP8LPutBits(bw, !TRANSFORM_PRESENT, 1); // No more transforms. - - // --------------------------------------------------------------------------- - // Encode and write the transformed image. - err = EncodeImageInternal(bw, enc->argb_, &enc->hash_chain_, enc->refs_, - enc->current_width_, height, quality, low_effort, - use_cache, &enc->cache_bits_, enc->histo_bits_, - byte_position, &hdr_size, &data_size); - if (err != VP8_ENC_OK) goto Error; - - if (picture->stats != NULL) { - WebPAuxStats* const stats = picture->stats; - stats->lossless_features = 0; - if (enc->use_predict_) stats->lossless_features |= 1; - if (enc->use_cross_color_) stats->lossless_features |= 2; - if (enc->use_subtract_green_) stats->lossless_features |= 4; - if (enc->use_palette_) stats->lossless_features |= 8; - stats->histogram_bits = enc->histo_bits_; - stats->transform_bits = enc->transform_bits_; - stats->cache_bits = enc->cache_bits_; - stats->palette_size = enc->palette_size_; - stats->lossless_size = (int)(VP8LBitWriterNumBytes(bw) - byte_position); - stats->lossless_hdr_size = hdr_size; - stats->lossless_data_size = data_size; - } - - Error: - VP8LEncoderDelete(enc); +Error: + VP8LBitWriterWipeOut(&bw_side); + VP8LEncoderDelete(enc_main); + VP8LEncoderDelete(enc_side); return err; } +#undef CRUNCH_CONFIGS_MAX +#undef CRUNCH_CONFIGS_LZ77_MAX + int VP8LEncodeImage(const WebPConfig* const config, const WebPPicture* const picture) { int width, height; @@ -1642,11 +1953,13 @@ int VP8LEncodeImage(const WebPConfig* const config, if (!WebPReportProgress(picture, 100, &percent)) goto UserAbort; +#if !defined(WEBP_DISABLE_STATS) // Save size. if (picture->stats != NULL) { picture->stats->coded_size += (int)coded_size; picture->stats->lossless_size = (int)coded_size; } +#endif if (picture->extra_info != NULL) { const int mb_w = (width + 15) >> 4; diff --git a/3rdparty/libwebp/enc/vp8li_enc.h b/3rdparty/libwebp/src/enc/vp8li_enc.h similarity index 65% rename from 3rdparty/libwebp/enc/vp8li_enc.h rename to 3rdparty/libwebp/src/enc/vp8li_enc.h index 8c5fbcbb2e..298a4a0014 100644 --- a/3rdparty/libwebp/enc/vp8li_enc.h +++ b/3rdparty/libwebp/src/enc/vp8li_enc.h @@ -11,14 +11,23 @@ // // Author: Vikas Arora (vikaas.arora@gmail.com) -#ifndef WEBP_ENC_VP8LI_H_ -#define WEBP_ENC_VP8LI_H_ +#ifndef WEBP_ENC_VP8LI_ENC_H_ +#define WEBP_ENC_VP8LI_ENC_H_ -#include "./backward_references_enc.h" -#include "./histogram_enc.h" -#include "../utils/bit_writer_utils.h" -#include "../webp/encode.h" -#include "../webp/format_constants.h" +#ifdef HAVE_CONFIG_H +#include "src/webp/config.h" +#endif +// Either WEBP_NEAR_LOSSLESS is defined as 0 in config.h when compiling to +// disable near-lossless, or it is enabled by default. +#ifndef WEBP_NEAR_LOSSLESS +#define WEBP_NEAR_LOSSLESS 1 +#endif + +#include "src/enc/backward_references_enc.h" +#include "src/enc/histogram_enc.h" +#include "src/utils/bit_writer_utils.h" +#include "src/webp/encode.h" +#include "src/webp/format_constants.h" #ifdef __cplusplus extern "C" { @@ -27,16 +36,24 @@ extern "C" { // maximum value of transform_bits_ in VP8LEncoder. #define MAX_TRANSFORM_BITS 6 +typedef enum { + kEncoderNone = 0, + kEncoderARGB, + kEncoderNearLossless, + kEncoderPalette +} VP8LEncoderARGBContent; + typedef struct { const WebPConfig* config_; // user configuration and parameters const WebPPicture* pic_; // input picture. - uint32_t* argb_; // Transformed argb image data. - uint32_t* argb_scratch_; // Scratch memory for argb rows - // (used for prediction). - uint32_t* transform_data_; // Scratch memory for transform data. - uint32_t* transform_mem_; // Currently allocated memory. - size_t transform_mem_size_; // Currently allocated memory size. + uint32_t* argb_; // Transformed argb image data. + VP8LEncoderARGBContent argb_content_; // Content type of the argb buffer. + uint32_t* argb_scratch_; // Scratch memory for argb rows + // (used for prediction). + uint32_t* transform_data_; // Scratch memory for transform data. + uint32_t* transform_mem_; // Currently allocated memory. + size_t transform_mem_size_; // Currently allocated memory size. int current_width_; // Corresponds to packed image width. @@ -54,8 +71,7 @@ typedef struct { uint32_t palette_[MAX_PALETTE_SIZE]; // Some 'scratch' (potentially large) objects. - struct VP8LBackwardRefs refs_[2]; // Backward Refs array corresponding to - // LZ77 & RLE coding. + struct VP8LBackwardRefs refs_[3]; // Backward Refs array for temporaries. VP8LHashChain hash_chain_; // HashChain data for constructing // backward references. } VP8LEncoder; @@ -75,6 +91,13 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, const WebPPicture* const picture, VP8LBitWriter* const bw, int use_cache); +#if (WEBP_NEAR_LOSSLESS == 1) +// in near_lossless.c +// Near lossless preprocessing in RGB color-space. +int VP8ApplyNearLossless(const WebPPicture* const picture, int quality, + uint32_t* const argb_dst); +#endif + //------------------------------------------------------------------------------ // Image transforms in predictor.c. @@ -92,4 +115,4 @@ void VP8LColorSpaceTransform(int width, int height, int bits, int quality, } // extern "C" #endif -#endif /* WEBP_ENC_VP8LI_H_ */ +#endif /* WEBP_ENC_VP8LI_ENC_H_ */ diff --git a/3rdparty/libwebp/enc/webp_enc.c b/3rdparty/libwebp/src/enc/webp_enc.c similarity index 97% rename from 3rdparty/libwebp/enc/webp_enc.c rename to 3rdparty/libwebp/src/enc/webp_enc.c index f18461ef92..283cda8e7b 100644 --- a/3rdparty/libwebp/enc/webp_enc.c +++ b/3rdparty/libwebp/src/enc/webp_enc.c @@ -16,10 +16,10 @@ #include #include -#include "./cost_enc.h" -#include "./vp8i_enc.h" -#include "./vp8li_enc.h" -#include "../utils/utils.h" +#include "src/enc/cost_enc.h" +#include "src/enc/vp8i_enc.h" +#include "src/enc/vp8li_enc.h" +#include "src/utils/utils.h" // #define PRINT_MEMORY_INFO @@ -207,7 +207,7 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config, enc->preds_w_ = preds_w; enc->mb_info_ = (VP8MBInfo*)mem; mem += info_size; - enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_; + enc->preds_ = mem + 1 + enc->preds_w_; mem += preds_size; enc->nz_ = 1 + (uint32_t*)WEBP_ALIGN(mem); mem += nz_size; @@ -216,7 +216,7 @@ static VP8Encoder* InitVP8Encoder(const WebPConfig* const config, // top samples (all 16-aligned) mem = (uint8_t*)WEBP_ALIGN(mem); - enc->y_top_ = (uint8_t*)mem; + enc->y_top_ = mem; enc->uv_top_ = enc->y_top_ + top_stride; mem += 2 * top_stride; assert(mem <= (uint8_t*)enc + size); @@ -256,6 +256,7 @@ static int DeleteVP8Encoder(VP8Encoder* enc) { //------------------------------------------------------------------------------ +#if !defined(WEBP_DISABLE_STATS) static double GetPSNR(uint64_t err, uint64_t size) { return (err > 0 && size > 0) ? 10. * log10(255. * 255. * size / err) : 99.; } @@ -270,8 +271,10 @@ static void FinalizePSNR(const VP8Encoder* const enc) { stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2); stats->PSNR[4] = (float)GetPSNR(sse[3], size); } +#endif // !defined(WEBP_DISABLE_STATS) static void StoreStats(VP8Encoder* const enc) { +#if !defined(WEBP_DISABLE_STATS) WebPAuxStats* const stats = enc->pic_->stats; if (stats != NULL) { int i, s; @@ -288,7 +291,9 @@ static void StoreStats(VP8Encoder* const enc) { stats->block_count[i] = enc->block_count_[i]; } } +#else // defined(WEBP_DISABLE_STATS) WebPReportProgress(enc->pic_, 100, &enc->percent_); // done! +#endif // !defined(WEBP_DISABLE_STATS) } int WebPEncodingSetError(const WebPPicture* const pic, @@ -336,10 +341,6 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) { if (!config->lossless) { VP8Encoder* enc = NULL; - if (!config->exact) { - WebPCleanupTransparentArea(pic); - } - if (pic->use_argb || pic->y == NULL || pic->u == NULL || pic->v == NULL) { // Make sure we have YUVA samples. if (config->use_sharp_yuv || (config->preprocessing & 4)) { @@ -361,6 +362,10 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) { } } + if (!config->exact) { + WebPCleanupTransparentArea(pic); + } + enc = InitVP8Encoder(config, pic); if (enc == NULL) return 0; // pic->error is already set. // Note: each of the tasks below account for 20% in the progress report. diff --git a/3rdparty/libwebp/mux/anim_encode.c b/3rdparty/libwebp/src/mux/anim_encode.c similarity index 97% rename from 3rdparty/libwebp/mux/anim_encode.c rename to 3rdparty/libwebp/src/mux/anim_encode.c index 6066388727..7be99068f6 100644 --- a/3rdparty/libwebp/mux/anim_encode.c +++ b/3rdparty/libwebp/src/mux/anim_encode.c @@ -16,12 +16,12 @@ #include #include // for abs() -#include "../mux/animi.h" -#include "../utils/utils.h" -#include "../webp/decode.h" -#include "../webp/encode.h" -#include "../webp/format_constants.h" -#include "../webp/mux.h" +#include "src/mux/animi.h" +#include "src/utils/utils.h" +#include "src/webp/decode.h" +#include "src/webp/encode.h" +#include "src/webp/format_constants.h" +#include "src/webp/mux.h" #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf @@ -35,7 +35,7 @@ // Stores frame rectangle dimensions. typedef struct { int x_offset_, y_offset_, width_, height_; -} FrameRect; +} FrameRectangle; // Used to store two candidates of encoded data for an animation frame. One of // the two will be chosen later. @@ -50,7 +50,7 @@ struct WebPAnimEncoder { const int canvas_height_; // Canvas height. const WebPAnimEncoderOptions options_; // Global encoding options. - FrameRect prev_rect_; // Previous WebP frame rectangle. + FrameRectangle prev_rect_; // Previous WebP frame rectangle. WebPConfig last_config_; // Cached in case a re-encode is needed. WebPConfig last_config_reversed_; // If 'last_config_' uses lossless, then // this config uses lossy and vice versa; @@ -206,7 +206,7 @@ static void ClearRectangle(WebPPicture* const picture, } static void WebPUtilClearPic(WebPPicture* const picture, - const FrameRect* const rect) { + const FrameRectangle* const rect) { if (rect != NULL) { ClearRectangle(picture, rect->x_offset_, rect->y_offset_, rect->width_, rect->height_); @@ -400,7 +400,7 @@ static WEBP_INLINE int ComparePixelsLossy(const uint32_t* src, int src_step, return 1; } -static int IsEmptyRect(const FrameRect* const rect) { +static int IsEmptyRect(const FrameRectangle* const rect) { return (rect->width_ == 0) || (rect->height_ == 0); } @@ -413,7 +413,7 @@ static int QualityToMaxDiff(float quality) { // Assumes that an initial valid guess of change rectangle 'rect' is passed. static void MinimizeChangeRectangle(const WebPPicture* const src, const WebPPicture* const dst, - FrameRect* const rect, + FrameRectangle* const rect, int is_lossless, float quality) { int i, j; const ComparePixelsFunc compare_pixels = @@ -498,7 +498,7 @@ static void MinimizeChangeRectangle(const WebPPicture* const src, } // Snap rectangle to even offsets (and adjust dimensions if needed). -static WEBP_INLINE void SnapToEvenOffsets(FrameRect* const rect) { +static WEBP_INLINE void SnapToEvenOffsets(FrameRectangle* const rect) { rect->width_ += (rect->x_offset_ & 1); rect->height_ += (rect->y_offset_ & 1); rect->x_offset_ &= ~1; @@ -508,9 +508,9 @@ static WEBP_INLINE void SnapToEvenOffsets(FrameRect* const rect) { typedef struct { int should_try_; // Should try this set of parameters. int empty_rect_allowed_; // Frame with empty rectangle can be skipped. - FrameRect rect_ll_; // Frame rectangle for lossless compression. + FrameRectangle rect_ll_; // Frame rectangle for lossless compression. WebPPicture sub_frame_ll_; // Sub-frame pic for lossless compression. - FrameRect rect_lossy_; // Frame rectangle for lossy compression. + FrameRectangle rect_lossy_; // Frame rectangle for lossy compression. // Could be smaller than rect_ll_ as pixels // with small diffs can be ignored. WebPPicture sub_frame_lossy_; // Sub-frame pic for lossless compression. @@ -538,7 +538,8 @@ static void SubFrameParamsFree(SubFrameParams* const params) { static int GetSubRect(const WebPPicture* const prev_canvas, const WebPPicture* const curr_canvas, int is_key_frame, int is_first_frame, int empty_rect_allowed, - int is_lossless, float quality, FrameRect* const rect, + int is_lossless, float quality, + FrameRectangle* const rect, WebPPicture* const sub_frame) { if (!is_key_frame || is_first_frame) { // Optimize frame rectangle. // Note: This behaves as expected for first frame, as 'prev_canvas' is @@ -594,7 +595,7 @@ int WebPAnimEncoderRefineRect( const WebPPicture* const prev_canvas, const WebPPicture* const curr_canvas, int is_lossless, float quality, int* const x_offset, int* const y_offset, int* const width, int* const height) { - FrameRect rect; + FrameRectangle rect; const int right = clip(*x_offset + *width, 0, curr_canvas->width); const int left = clip(*x_offset, 0, curr_canvas->width - 1); const int bottom = clip(*y_offset + *height, 0, curr_canvas->height); @@ -620,7 +621,7 @@ int WebPAnimEncoderRefineRect( } static void DisposeFrameRectangle(int dispose_method, - const FrameRect* const rect, + const FrameRectangle* const rect, WebPPicture* const curr_canvas) { assert(rect != NULL); if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { @@ -628,13 +629,13 @@ static void DisposeFrameRectangle(int dispose_method, } } -static uint32_t RectArea(const FrameRect* const rect) { +static uint32_t RectArea(const FrameRectangle* const rect) { return (uint32_t)rect->width_ * rect->height_; } static int IsLosslessBlendingPossible(const WebPPicture* const src, const WebPPicture* const dst, - const FrameRect* const rect) { + const FrameRectangle* const rect) { int i, j; assert(src->width == dst->width && src->height == dst->height); assert(rect->x_offset_ + rect->width_ <= dst->width); @@ -656,7 +657,7 @@ static int IsLosslessBlendingPossible(const WebPPicture* const src, static int IsLossyBlendingPossible(const WebPPicture* const src, const WebPPicture* const dst, - const FrameRect* const rect, + const FrameRectangle* const rect, float quality) { const int max_allowed_diff_lossy = QualityToMaxDiff(quality); int i, j; @@ -683,7 +684,7 @@ static int IsLossyBlendingPossible(const WebPPicture* const src, // transparent pixels. // Returns true if at least one pixel gets modified. static int IncreaseTransparency(const WebPPicture* const src, - const FrameRect* const rect, + const FrameRectangle* const rect, WebPPicture* const dst) { int i, j; int modified = 0; @@ -709,7 +710,7 @@ static int IncreaseTransparency(const WebPPicture* const src, // Assumes lossy compression is being used. // Returns true if at least one pixel gets modified. static int FlattenSimilarBlocks(const WebPPicture* const src, - const FrameRect* const rect, + const FrameRectangle* const rect, WebPPicture* const dst, float quality) { const int max_allowed_diff_lossy = QualityToMaxDiff(quality); int i, j; @@ -778,13 +779,13 @@ static int EncodeFrame(const WebPConfig* const config, WebPPicture* const pic, typedef struct { WebPMemoryWriter mem_; WebPMuxFrameInfo info_; - FrameRect rect_; + FrameRectangle rect_; int evaluate_; // True if this candidate should be evaluated. } Candidate; // Generates a candidate encoded frame given a picture and metadata. static WebPEncodingError EncodeCandidate(WebPPicture* const sub_frame, - const FrameRect* const rect, + const FrameRectangle* const rect, const WebPConfig* const encoder_config, int use_blending, Candidate* const candidate) { @@ -958,7 +959,7 @@ static int IncreasePreviousDuration(WebPAnimEncoder* const enc, int duration) { if (new_duration >= MAX_DURATION) { // Special case. // Separate out previous frame from earlier merged frames to avoid overflow. // We add a 1x1 transparent frame for the previous frame, with blending on. - const FrameRect rect = { 0, 0, 1, 1 }; + const FrameRectangle rect = { 0, 0, 1, 1 }; const uint8_t lossless_1x1_bytes[] = { 0x52, 0x49, 0x46, 0x46, 0x14, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, 0x56, 0x50, 0x38, 0x4c, 0x08, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, @@ -1223,7 +1224,7 @@ static int CacheFrame(WebPAnimEncoder* const enc, enc->prev_candidate_undecided_ = 0; } else { int64_t curr_delta; - FrameRect prev_rect_key, prev_rect_sub; + FrameRectangle prev_rect_key, prev_rect_sub; // Add this as a frame rectangle to enc. error_code = SetFrame(enc, config, 0, encoded_frame, &frame_skipped); @@ -1535,7 +1536,8 @@ int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, WebPData* webp_data) { if (!enc->got_null_frame_ && enc->in_frame_count_ > 1 && enc->count_ > 0) { // set duration of the last frame to be avg of durations of previous frames. - const double delta_time = enc->prev_timestamp_ - enc->first_timestamp_; + const double delta_time = + (uint32_t)enc->prev_timestamp_ - enc->first_timestamp_; const int average_duration = (int)(delta_time / (enc->in_frame_count_ - 1)); if (!IncreasePreviousDuration(enc, average_duration)) { return 0; diff --git a/3rdparty/libwebp/mux/animi.h b/3rdparty/libwebp/src/mux/animi.h similarity index 98% rename from 3rdparty/libwebp/mux/animi.h rename to 3rdparty/libwebp/src/mux/animi.h index cecaf1fee5..88899532aa 100644 --- a/3rdparty/libwebp/mux/animi.h +++ b/3rdparty/libwebp/src/mux/animi.h @@ -14,7 +14,7 @@ #ifndef WEBP_MUX_ANIMI_H_ #define WEBP_MUX_ANIMI_H_ -#include "../webp/mux.h" +#include "src/webp/mux.h" #ifdef __cplusplus extern "C" { diff --git a/3rdparty/libwebp/mux/muxedit.c b/3rdparty/libwebp/src/mux/muxedit.c similarity index 99% rename from 3rdparty/libwebp/mux/muxedit.c rename to 3rdparty/libwebp/src/mux/muxedit.c index d2c5305372..7a027b3cb4 100644 --- a/3rdparty/libwebp/mux/muxedit.c +++ b/3rdparty/libwebp/src/mux/muxedit.c @@ -13,8 +13,8 @@ // Vikas (vikasa@google.com) #include -#include "./muxi.h" -#include "../utils/utils.h" +#include "src/mux/muxi.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // Life of a mux object. diff --git a/3rdparty/libwebp/mux/muxi.h b/3rdparty/libwebp/src/mux/muxi.h similarity index 98% rename from 3rdparty/libwebp/mux/muxi.h rename to 3rdparty/libwebp/src/mux/muxi.h index e6606aa5d1..b73e3fbd7a 100644 --- a/3rdparty/libwebp/mux/muxi.h +++ b/3rdparty/libwebp/src/mux/muxi.h @@ -15,9 +15,9 @@ #define WEBP_MUX_MUXI_H_ #include -#include "../dec/vp8i_dec.h" -#include "../dec/vp8li_dec.h" -#include "../webp/mux.h" +#include "src/dec/vp8i_dec.h" +#include "src/dec/vp8li_dec.h" +#include "src/webp/mux.h" #ifdef __cplusplus extern "C" { @@ -28,7 +28,7 @@ extern "C" { #define MUX_MAJ_VERSION 0 #define MUX_MIN_VERSION 4 -#define MUX_REV_VERSION 0 +#define MUX_REV_VERSION 1 // Chunk object. typedef struct WebPChunk WebPChunk; diff --git a/3rdparty/libwebp/mux/muxinternal.c b/3rdparty/libwebp/src/mux/muxinternal.c similarity index 96% rename from 3rdparty/libwebp/mux/muxinternal.c rename to 3rdparty/libwebp/src/mux/muxinternal.c index 387b57e8fe..1473f100e5 100644 --- a/3rdparty/libwebp/mux/muxinternal.c +++ b/3rdparty/libwebp/src/mux/muxinternal.c @@ -13,8 +13,8 @@ // Vikas (vikasa@google.com) #include -#include "./muxi.h" -#include "../utils/utils.h" +#include "src/mux/muxi.h" +#include "src/utils/utils.h" #define UNDEFINED_CHUNK_SIZE ((uint32_t)(-1)) @@ -504,6 +504,20 @@ WebPMuxError MuxValidate(const WebPMux* const mux) { if (!has_animation && (num_anim == 1 || num_frames > 0)) { return WEBP_MUX_INVALID_ARGUMENT; } + if (!has_animation) { + const WebPMuxImage* images = mux->images_; + // There can be only one image. + if (images == NULL || images->next_ != NULL) { + return WEBP_MUX_INVALID_ARGUMENT; + } + // Size must match. + if (mux->canvas_width_ > 0) { + if (images->width_ != mux->canvas_width_ || + images->height_ != mux->canvas_height_) { + return WEBP_MUX_INVALID_ARGUMENT; + } + } + } } // Verify either VP8X chunk is present OR there is only one elem in @@ -515,6 +529,7 @@ WebPMuxError MuxValidate(const WebPMux* const mux) { if (num_vp8x == 0 && num_images != 1) return WEBP_MUX_INVALID_ARGUMENT; // ALPHA_FLAG & alpha chunk(s) are consistent. + // Note: ALPHA_FLAG can be set when there is actually no Alpha data present. if (MuxHasAlpha(mux->images_)) { if (num_vp8x > 0) { // VP8X chunk is present, so it should contain ALPHA_FLAG. @@ -525,8 +540,6 @@ WebPMuxError MuxValidate(const WebPMux* const mux) { if (err != WEBP_MUX_OK) return err; if (num_alpha > 0) return WEBP_MUX_INVALID_ARGUMENT; } - } else { // Mux doesn't need alpha. So, ALPHA_FLAG should NOT be present. - if (flags & ALPHA_FLAG) return WEBP_MUX_INVALID_ARGUMENT; } return WEBP_MUX_OK; diff --git a/3rdparty/libwebp/mux/muxread.c b/3rdparty/libwebp/src/mux/muxread.c similarity index 99% rename from 3rdparty/libwebp/mux/muxread.c rename to 3rdparty/libwebp/src/mux/muxread.c index 410acd9119..0b55286862 100644 --- a/3rdparty/libwebp/mux/muxread.c +++ b/3rdparty/libwebp/src/mux/muxread.c @@ -13,8 +13,8 @@ // Vikas (vikasa@google.com) #include -#include "./muxi.h" -#include "../utils/utils.h" +#include "src/mux/muxi.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // Helper method(s). @@ -43,7 +43,7 @@ static WebPMuxError MuxGet(const WebPMux* const mux, CHUNK_INDEX idx, SWITCH_ID_LIST(IDX_ANIM, mux->anim_); SWITCH_ID_LIST(IDX_EXIF, mux->exif_); SWITCH_ID_LIST(IDX_XMP, mux->xmp_); - SWITCH_ID_LIST(IDX_UNKNOWN, mux->unknown_); + assert(idx != IDX_UNKNOWN); return WEBP_MUX_NOT_FOUND; } #undef SWITCH_ID_LIST @@ -270,6 +270,9 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data, ChunkInit(&chunk); } + // Incomplete image. + if (wpi->is_partial_) goto Err; + // Validate mux if complete. if (MuxValidate(mux) != WEBP_MUX_OK) goto Err; diff --git a/3rdparty/libwebp/utils/bit_reader_inl_utils.h b/3rdparty/libwebp/src/utils/bit_reader_inl_utils.h similarity index 94% rename from 3rdparty/libwebp/utils/bit_reader_inl_utils.h rename to 3rdparty/libwebp/src/utils/bit_reader_inl_utils.h index fd7fb0446c..2ccc6ed326 100644 --- a/3rdparty/libwebp/utils/bit_reader_inl_utils.h +++ b/3rdparty/libwebp/src/utils/bit_reader_inl_utils.h @@ -13,19 +13,19 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_UTILS_BIT_READER_INL_H_ -#define WEBP_UTILS_BIT_READER_INL_H_ +#ifndef WEBP_UTILS_BIT_READER_INL_UTILS_H_ +#define WEBP_UTILS_BIT_READER_INL_UTILS_H_ #ifdef HAVE_CONFIG_H -#include "../webp/config.h" +#include "src/webp/config.h" #endif #include // for memcpy -#include "../dsp/dsp.h" -#include "./bit_reader_utils.h" -#include "./endian_inl_utils.h" -#include "./utils.h" +#include "src/dsp/dsp.h" +#include "src/utils/bit_reader_utils.h" +#include "src/utils/endian_inl_utils.h" +#include "src/utils/utils.h" #ifdef __cplusplus extern "C" { @@ -187,4 +187,4 @@ static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) { } // extern "C" #endif -#endif // WEBP_UTILS_BIT_READER_INL_H_ +#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_ diff --git a/3rdparty/libwebp/utils/bit_reader_utils.c b/3rdparty/libwebp/src/utils/bit_reader_utils.c similarity index 98% rename from 3rdparty/libwebp/utils/bit_reader_utils.c rename to 3rdparty/libwebp/src/utils/bit_reader_utils.c index c3157e8fe8..1500354d5c 100644 --- a/3rdparty/libwebp/utils/bit_reader_utils.c +++ b/3rdparty/libwebp/src/utils/bit_reader_utils.c @@ -12,11 +12,11 @@ // Author: Skal (pascal.massimino@gmail.com) #ifdef HAVE_CONFIG_H -#include "../webp/config.h" +#include "src/webp/config.h" #endif -#include "./bit_reader_inl_utils.h" -#include "../utils/utils.h" +#include "src/utils/bit_reader_inl_utils.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // VP8BitReader diff --git a/3rdparty/libwebp/utils/bit_reader_utils.h b/3rdparty/libwebp/src/utils/bit_reader_utils.h similarity index 96% rename from 3rdparty/libwebp/utils/bit_reader_utils.h rename to 3rdparty/libwebp/src/utils/bit_reader_utils.h index ec3426cd11..317d311c17 100644 --- a/3rdparty/libwebp/utils/bit_reader_utils.h +++ b/3rdparty/libwebp/src/utils/bit_reader_utils.h @@ -12,14 +12,14 @@ // Author: Skal (pascal.massimino@gmail.com) // Vikas Arora (vikaas.arora@gmail.com) -#ifndef WEBP_UTILS_BIT_READER_H_ -#define WEBP_UTILS_BIT_READER_H_ +#ifndef WEBP_UTILS_BIT_READER_UTILS_H_ +#define WEBP_UTILS_BIT_READER_UTILS_H_ #include #ifdef _MSC_VER #include // _byteswap_ulong #endif -#include "../webp/types.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -155,9 +155,10 @@ static WEBP_INLINE int VP8LIsEndOfStream(const VP8LBitReader* const br) { // For jumping over a number of bits in the bit stream when accessed with // VP8LPrefetchBits and VP8LFillBitWindow. +// This function does *not* set br->eos_, since it's speed-critical. +// Use with extreme care! static WEBP_INLINE void VP8LSetBitPos(VP8LBitReader* const br, int val) { br->bit_pos_ = val; - br->eos_ = VP8LIsEndOfStream(br); } // Advances the read buffer by 4 bytes to make room for reading next 32 bits. @@ -171,4 +172,4 @@ static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) { } // extern "C" #endif -#endif /* WEBP_UTILS_BIT_READER_H_ */ +#endif /* WEBP_UTILS_BIT_READER_UTILS_H_ */ diff --git a/3rdparty/libwebp/utils/bit_writer_utils.c b/3rdparty/libwebp/src/utils/bit_writer_utils.c similarity index 91% rename from 3rdparty/libwebp/utils/bit_writer_utils.c rename to 3rdparty/libwebp/src/utils/bit_writer_utils.c index ab0c49dce8..f4f476ce3f 100644 --- a/3rdparty/libwebp/utils/bit_writer_utils.c +++ b/3rdparty/libwebp/src/utils/bit_writer_utils.c @@ -16,9 +16,9 @@ #include // for memcpy() #include -#include "./bit_writer_utils.h" -#include "./endian_inl_utils.h" -#include "./utils.h" +#include "src/utils/bit_writer_utils.h" +#include "src/utils/endian_inl_utils.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // VP8BitWriter @@ -239,6 +239,18 @@ int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size) { return VP8LBitWriterResize(bw, expected_size); } +int VP8LBitWriterClone(const VP8LBitWriter* const src, + VP8LBitWriter* const dst) { + const size_t current_size = src->cur_ - src->buf_; + assert(src->cur_ >= src->buf_ && src->cur_ <= src->end_); + if (!VP8LBitWriterResize(dst, current_size)) return 0; + memcpy(dst->buf_, src->buf_, current_size); + dst->bits_ = src->bits_; + dst->used_ = src->used_; + dst->error_ = src->error_; + return 1; +} + void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) { if (bw != NULL) { WebPSafeFree(bw->buf_); @@ -246,6 +258,21 @@ void VP8LBitWriterWipeOut(VP8LBitWriter* const bw) { } } +void VP8LBitWriterReset(const VP8LBitWriter* const bw_init, + VP8LBitWriter* const bw) { + bw->bits_ = bw_init->bits_; + bw->used_ = bw_init->used_; + bw->cur_ = bw->buf_ + (bw_init->cur_ - bw_init->buf_); + assert(bw->cur_ <= bw->end_); + bw->error_ = bw_init->error_; +} + +void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst) { + const VP8LBitWriter tmp = *src; + *src = *dst; + *dst = tmp; +} + void VP8LPutBitsFlushBits(VP8LBitWriter* const bw) { // If needed, make some room by flushing some bits out. if (bw->cur_ + VP8L_WRITER_BYTES > bw->end_) { diff --git a/3rdparty/libwebp/utils/bit_writer_utils.h b/3rdparty/libwebp/src/utils/bit_writer_utils.h similarity index 88% rename from 3rdparty/libwebp/utils/bit_writer_utils.h rename to 3rdparty/libwebp/src/utils/bit_writer_utils.h index 9c02bbc06d..2cf5976fe3 100644 --- a/3rdparty/libwebp/utils/bit_writer_utils.h +++ b/3rdparty/libwebp/src/utils/bit_writer_utils.h @@ -11,10 +11,10 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_UTILS_BIT_WRITER_H_ -#define WEBP_UTILS_BIT_WRITER_H_ +#ifndef WEBP_UTILS_BIT_WRITER_UTILS_H_ +#define WEBP_UTILS_BIT_WRITER_UTILS_H_ -#include "../webp/types.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -100,16 +100,24 @@ typedef struct { int error_; } VP8LBitWriter; -static WEBP_INLINE size_t VP8LBitWriterNumBytes(VP8LBitWriter* const bw) { +static WEBP_INLINE size_t VP8LBitWriterNumBytes(const VP8LBitWriter* const bw) { return (bw->cur_ - bw->buf_) + ((bw->used_ + 7) >> 3); } // Returns false in case of memory allocation error. int VP8LBitWriterInit(VP8LBitWriter* const bw, size_t expected_size); +// Returns false in case of memory allocation error. +int VP8LBitWriterClone(const VP8LBitWriter* const src, + VP8LBitWriter* const dst); // Finalize the bitstream coding. Returns a pointer to the internal buffer. uint8_t* VP8LBitWriterFinish(VP8LBitWriter* const bw); // Release any pending memory and zeroes the object. void VP8LBitWriterWipeOut(VP8LBitWriter* const bw); +// Resets the cursor of the BitWriter bw to when it was like in bw_init. +void VP8LBitWriterReset(const VP8LBitWriter* const bw_init, + VP8LBitWriter* const bw); +// Swaps the memory held by two BitWriters. +void VP8LBitWriterSwap(VP8LBitWriter* const src, VP8LBitWriter* const dst); // Internal function for VP8LPutBits flushing 32 bits from the written state. void VP8LPutBitsFlushBits(VP8LBitWriter* const bw); @@ -143,4 +151,4 @@ static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw, } // extern "C" #endif -#endif /* WEBP_UTILS_BIT_WRITER_H_ */ +#endif /* WEBP_UTILS_BIT_WRITER_UTILS_H_ */ diff --git a/3rdparty/libwebp/utils/color_cache_utils.c b/3rdparty/libwebp/src/utils/color_cache_utils.c similarity index 95% rename from 3rdparty/libwebp/utils/color_cache_utils.c rename to 3rdparty/libwebp/src/utils/color_cache_utils.c index 0172590c48..b09f538e8b 100644 --- a/3rdparty/libwebp/utils/color_cache_utils.c +++ b/3rdparty/libwebp/src/utils/color_cache_utils.c @@ -14,8 +14,8 @@ #include #include #include -#include "./color_cache_utils.h" -#include "./utils.h" +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" //------------------------------------------------------------------------------ // VP8LColorCache. diff --git a/3rdparty/libwebp/utils/color_cache_utils.h b/3rdparty/libwebp/src/utils/color_cache_utils.h similarity index 86% rename from 3rdparty/libwebp/utils/color_cache_utils.h rename to 3rdparty/libwebp/src/utils/color_cache_utils.h index c373e6b361..20b7be11c9 100644 --- a/3rdparty/libwebp/utils/color_cache_utils.h +++ b/3rdparty/libwebp/src/utils/color_cache_utils.h @@ -12,10 +12,12 @@ // Authors: Jyrki Alakuijala (jyrki@google.com) // Urvang Joshi (urvang@google.com) -#ifndef WEBP_UTILS_COLOR_CACHE_H_ -#define WEBP_UTILS_COLOR_CACHE_H_ +#ifndef WEBP_UTILS_COLOR_CACHE_UTILS_H_ +#define WEBP_UTILS_COLOR_CACHE_UTILS_H_ -#include "../webp/types.h" +#include + +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -30,7 +32,7 @@ typedef struct { static const uint64_t kHashMul = 0x1e35a7bdull; -static WEBP_INLINE int HashPix(uint32_t argb, int shift) { +static WEBP_INLINE int VP8LHashPix(uint32_t argb, int shift) { return (int)(((argb * kHashMul) & 0xffffffffu) >> shift); } @@ -48,19 +50,19 @@ static WEBP_INLINE void VP8LColorCacheSet(const VP8LColorCache* const cc, static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc, uint32_t argb) { - const int key = HashPix(argb, cc->hash_shift_); + const int key = VP8LHashPix(argb, cc->hash_shift_); cc->colors_[key] = argb; } static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc, uint32_t argb) { - return HashPix(argb, cc->hash_shift_); + return VP8LHashPix(argb, cc->hash_shift_); } // Return the key if cc contains argb, and -1 otherwise. static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc, uint32_t argb) { - const int key = HashPix(argb, cc->hash_shift_); + const int key = VP8LHashPix(argb, cc->hash_shift_); return (cc->colors_[key] == argb) ? key : -1; } @@ -82,4 +84,4 @@ void VP8LColorCacheClear(VP8LColorCache* const color_cache); } #endif -#endif // WEBP_UTILS_COLOR_CACHE_H_ +#endif // WEBP_UTILS_COLOR_CACHE_UTILS_H_ diff --git a/3rdparty/libwebp/utils/endian_inl_utils.h b/3rdparty/libwebp/src/utils/endian_inl_utils.h similarity index 93% rename from 3rdparty/libwebp/utils/endian_inl_utils.h rename to 3rdparty/libwebp/src/utils/endian_inl_utils.h index e11260ff7d..4b2f91dfb8 100644 --- a/3rdparty/libwebp/utils/endian_inl_utils.h +++ b/3rdparty/libwebp/src/utils/endian_inl_utils.h @@ -9,15 +9,15 @@ // // Endian related functions. -#ifndef WEBP_UTILS_ENDIAN_INL_H_ -#define WEBP_UTILS_ENDIAN_INL_H_ +#ifndef WEBP_UTILS_ENDIAN_INL_UTILS_H_ +#define WEBP_UTILS_ENDIAN_INL_UTILS_H_ #ifdef HAVE_CONFIG_H -#include "../webp/config.h" +#include "src/webp/config.h" #endif -#include "../dsp/dsp.h" -#include "../webp/types.h" +#include "src/dsp/dsp.h" +#include "src/webp/types.h" // some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__) #if !defined(WORDS_BIGENDIAN) && \ @@ -97,4 +97,4 @@ static WEBP_INLINE uint64_t BSwap64(uint64_t x) { #endif // HAVE_BUILTIN_BSWAP64 } -#endif // WEBP_UTILS_ENDIAN_INL_H_ +#endif // WEBP_UTILS_ENDIAN_INL_UTILS_H_ diff --git a/3rdparty/libwebp/utils/filters_utils.c b/3rdparty/libwebp/src/utils/filters_utils.c similarity index 98% rename from 3rdparty/libwebp/utils/filters_utils.c rename to 3rdparty/libwebp/src/utils/filters_utils.c index 49c1d18a22..bbc2c34d93 100644 --- a/3rdparty/libwebp/utils/filters_utils.c +++ b/3rdparty/libwebp/src/utils/filters_utils.c @@ -11,7 +11,7 @@ // // Author: Urvang (urvang@google.com) -#include "./filters_utils.h" +#include "src/utils/filters_utils.h" #include #include diff --git a/3rdparty/libwebp/utils/filters_utils.h b/3rdparty/libwebp/src/utils/filters_utils.h similarity index 83% rename from 3rdparty/libwebp/utils/filters_utils.h rename to 3rdparty/libwebp/src/utils/filters_utils.h index 088b132fc5..410f2fcdf2 100644 --- a/3rdparty/libwebp/utils/filters_utils.h +++ b/3rdparty/libwebp/src/utils/filters_utils.h @@ -11,11 +11,11 @@ // // Author: Urvang (urvang@google.com) -#ifndef WEBP_UTILS_FILTERS_H_ -#define WEBP_UTILS_FILTERS_H_ +#ifndef WEBP_UTILS_FILTERS_UTILS_H_ +#define WEBP_UTILS_FILTERS_UTILS_H_ -#include "../webp/types.h" -#include "../dsp/dsp.h" +#include "src/webp/types.h" +#include "src/dsp/dsp.h" #ifdef __cplusplus extern "C" { @@ -29,4 +29,4 @@ WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data, } // extern "C" #endif -#endif /* WEBP_UTILS_FILTERS_H_ */ +#endif /* WEBP_UTILS_FILTERS_UTILS_H_ */ diff --git a/3rdparty/libwebp/utils/huffman_encode_utils.c b/3rdparty/libwebp/src/utils/huffman_encode_utils.c similarity index 99% rename from 3rdparty/libwebp/utils/huffman_encode_utils.c rename to 3rdparty/libwebp/src/utils/huffman_encode_utils.c index f9504658ea..6f3b1bbe02 100644 --- a/3rdparty/libwebp/utils/huffman_encode_utils.c +++ b/3rdparty/libwebp/src/utils/huffman_encode_utils.c @@ -14,9 +14,9 @@ #include #include #include -#include "./huffman_encode_utils.h" -#include "./utils.h" -#include "../webp/format_constants.h" +#include "src/utils/huffman_encode_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" // ----------------------------------------------------------------------------- // Util function to optimize the symbol map for RLE coding diff --git a/3rdparty/libwebp/utils/huffman_encode_utils.h b/3rdparty/libwebp/src/utils/huffman_encode_utils.h similarity index 92% rename from 3rdparty/libwebp/utils/huffman_encode_utils.h rename to 3rdparty/libwebp/src/utils/huffman_encode_utils.h index a157165148..3e6763ce49 100644 --- a/3rdparty/libwebp/utils/huffman_encode_utils.h +++ b/3rdparty/libwebp/src/utils/huffman_encode_utils.h @@ -11,10 +11,10 @@ // // Entropy encoding (Huffman) for webp lossless -#ifndef WEBP_UTILS_HUFFMAN_ENCODE_H_ -#define WEBP_UTILS_HUFFMAN_ENCODE_H_ +#ifndef WEBP_UTILS_HUFFMAN_ENCODE_UTILS_H_ +#define WEBP_UTILS_HUFFMAN_ENCODE_UTILS_H_ -#include "../webp/types.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -57,4 +57,4 @@ void VP8LCreateHuffmanTree(uint32_t* const histogram, int tree_depth_limit, } #endif -#endif // WEBP_UTILS_HUFFMAN_ENCODE_H_ +#endif // WEBP_UTILS_HUFFMAN_ENCODE_UTILS_H_ diff --git a/3rdparty/libwebp/utils/huffman_utils.c b/3rdparty/libwebp/src/utils/huffman_utils.c similarity index 98% rename from 3rdparty/libwebp/utils/huffman_utils.c rename to 3rdparty/libwebp/src/utils/huffman_utils.c index 008b5d746f..7a69963c3e 100644 --- a/3rdparty/libwebp/utils/huffman_utils.c +++ b/3rdparty/libwebp/src/utils/huffman_utils.c @@ -14,9 +14,9 @@ #include #include #include -#include "./huffman_utils.h" -#include "./utils.h" -#include "../webp/format_constants.h" +#include "src/utils/huffman_utils.h" +#include "src/utils/utils.h" +#include "src/webp/format_constants.h" // Huffman data read via DecodeImageStream is represented in two (red and green) // bytes. diff --git a/3rdparty/libwebp/utils/huffman_utils.h b/3rdparty/libwebp/src/utils/huffman_utils.h similarity index 94% rename from 3rdparty/libwebp/utils/huffman_utils.h rename to 3rdparty/libwebp/src/utils/huffman_utils.h index c6dd6aaa45..ff7ef17f3b 100644 --- a/3rdparty/libwebp/utils/huffman_utils.h +++ b/3rdparty/libwebp/src/utils/huffman_utils.h @@ -11,12 +11,12 @@ // // Author: Urvang Joshi (urvang@google.com) -#ifndef WEBP_UTILS_HUFFMAN_H_ -#define WEBP_UTILS_HUFFMAN_H_ +#ifndef WEBP_UTILS_HUFFMAN_UTILS_H_ +#define WEBP_UTILS_HUFFMAN_UTILS_H_ #include -#include "../webp/format_constants.h" -#include "../webp/types.h" +#include "src/webp/format_constants.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -85,4 +85,4 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits, } // extern "C" #endif -#endif // WEBP_UTILS_HUFFMAN_H_ +#endif // WEBP_UTILS_HUFFMAN_UTILS_H_ diff --git a/3rdparty/libwebp/utils/quant_levels_dec_utils.c b/3rdparty/libwebp/src/utils/quant_levels_dec_utils.c similarity index 97% rename from 3rdparty/libwebp/utils/quant_levels_dec_utils.c rename to 3rdparty/libwebp/src/utils/quant_levels_dec_utils.c index d4d23d3147..3818a78b93 100644 --- a/3rdparty/libwebp/utils/quant_levels_dec_utils.c +++ b/3rdparty/libwebp/src/utils/quant_levels_dec_utils.c @@ -14,11 +14,11 @@ // // Author: Skal (pascal.massimino@gmail.com) -#include "./quant_levels_dec_utils.h" +#include "src/utils/quant_levels_dec_utils.h" #include // for memset -#include "./utils.h" +#include "src/utils/utils.h" // #define USE_DITHERING // uncomment to enable ordered dithering (not vital) @@ -71,10 +71,11 @@ typedef struct { //------------------------------------------------------------------------------ -#define CLIP_MASK (int)(~0U << (8 + DFIX)) +#define CLIP_8b_MASK (int)(~0U << (8 + DFIX)) static WEBP_INLINE uint8_t clip_8b(int v) { - return (!(v & CLIP_MASK)) ? (uint8_t)(v >> DFIX) : (v < 0) ? 0u : 255u; + return (!(v & CLIP_8b_MASK)) ? (uint8_t)(v >> DFIX) : (v < 0) ? 0u : 255u; } +#undef CLIP_8b_MASK // vertical accumulation static void VFilter(SmoothParams* const p) { diff --git a/3rdparty/libwebp/utils/quant_levels_dec_utils.h b/3rdparty/libwebp/src/utils/quant_levels_dec_utils.h similarity index 86% rename from 3rdparty/libwebp/utils/quant_levels_dec_utils.h rename to 3rdparty/libwebp/src/utils/quant_levels_dec_utils.h index 59a13495d3..f822107a72 100644 --- a/3rdparty/libwebp/utils/quant_levels_dec_utils.h +++ b/3rdparty/libwebp/src/utils/quant_levels_dec_utils.h @@ -11,10 +11,10 @@ // // Author: Vikas Arora (vikasa@google.com) -#ifndef WEBP_UTILS_QUANT_LEVELS_DEC_H_ -#define WEBP_UTILS_QUANT_LEVELS_DEC_H_ +#ifndef WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ +#define WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ -#include "../webp/types.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -32,4 +32,4 @@ int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, } // extern "C" #endif -#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_H_ */ +#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ */ diff --git a/3rdparty/libwebp/utils/quant_levels_utils.c b/3rdparty/libwebp/src/utils/quant_levels_utils.c similarity index 98% rename from 3rdparty/libwebp/utils/quant_levels_utils.c rename to 3rdparty/libwebp/src/utils/quant_levels_utils.c index 73174e8ab9..d65ad3c29d 100644 --- a/3rdparty/libwebp/utils/quant_levels_utils.c +++ b/3rdparty/libwebp/src/utils/quant_levels_utils.c @@ -14,7 +14,7 @@ #include -#include "./quant_levels_utils.h" +#include "src/utils/quant_levels_utils.h" #define NUM_SYMBOLS 256 diff --git a/3rdparty/libwebp/utils/quant_levels_utils.h b/3rdparty/libwebp/src/utils/quant_levels_utils.h similarity index 86% rename from 3rdparty/libwebp/utils/quant_levels_utils.h rename to 3rdparty/libwebp/src/utils/quant_levels_utils.h index 1cb5a32cae..75df2ba6a4 100644 --- a/3rdparty/libwebp/utils/quant_levels_utils.h +++ b/3rdparty/libwebp/src/utils/quant_levels_utils.h @@ -11,12 +11,12 @@ // // Author: Vikas Arora (vikasa@google.com) -#ifndef WEBP_UTILS_QUANT_LEVELS_H_ -#define WEBP_UTILS_QUANT_LEVELS_H_ +#ifndef WEBP_UTILS_QUANT_LEVELS_UTILS_H_ +#define WEBP_UTILS_QUANT_LEVELS_UTILS_H_ #include -#include "../webp/types.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -33,4 +33,4 @@ int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels, } // extern "C" #endif -#endif /* WEBP_UTILS_QUANT_LEVELS_H_ */ +#endif /* WEBP_UTILS_QUANT_LEVELS_UTILS_H_ */ diff --git a/3rdparty/libwebp/utils/random_utils.c b/3rdparty/libwebp/src/utils/random_utils.c similarity index 98% rename from 3rdparty/libwebp/utils/random_utils.c rename to 3rdparty/libwebp/src/utils/random_utils.c index 9f1e4154a6..7edb3fefbb 100644 --- a/3rdparty/libwebp/utils/random_utils.c +++ b/3rdparty/libwebp/src/utils/random_utils.c @@ -12,7 +12,7 @@ // Author: Skal (pascal.massimino@gmail.com) #include -#include "./random_utils.h" +#include "src/utils/random_utils.h" //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/utils/random_utils.h b/3rdparty/libwebp/src/utils/random_utils.h similarity index 93% rename from 3rdparty/libwebp/utils/random_utils.h rename to 3rdparty/libwebp/src/utils/random_utils.h index c392a615ca..6d36c667e7 100644 --- a/3rdparty/libwebp/utils/random_utils.h +++ b/3rdparty/libwebp/src/utils/random_utils.h @@ -11,11 +11,11 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_UTILS_RANDOM_H_ -#define WEBP_UTILS_RANDOM_H_ +#ifndef WEBP_UTILS_RANDOM_UTILS_H_ +#define WEBP_UTILS_RANDOM_UTILS_H_ #include -#include "../webp/types.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -60,4 +60,4 @@ static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) { } // extern "C" #endif -#endif /* WEBP_UTILS_RANDOM_H_ */ +#endif /* WEBP_UTILS_RANDOM_UTILS_H_ */ diff --git a/3rdparty/libwebp/utils/rescaler_utils.c b/3rdparty/libwebp/src/utils/rescaler_utils.c similarity index 95% rename from 3rdparty/libwebp/utils/rescaler_utils.c rename to 3rdparty/libwebp/src/utils/rescaler_utils.c index 0d1f80da24..90e2ea76a1 100644 --- a/3rdparty/libwebp/utils/rescaler_utils.c +++ b/3rdparty/libwebp/src/utils/rescaler_utils.c @@ -14,8 +14,8 @@ #include #include #include -#include "../dsp/dsp.h" -#include "./rescaler_utils.h" +#include "src/dsp/dsp.h" +#include "src/utils/rescaler_utils.h" //------------------------------------------------------------------------------ @@ -85,11 +85,13 @@ int WebPRescalerGetScaledDimensions(int src_width, int src_height, // if width is unspecified, scale original proportionally to height ratio. if (width == 0) { - width = (src_width * height + src_height / 2) / src_height; + width = + (int)(((uint64_t)src_width * height + src_height / 2) / src_height); } // if height is unspecified, scale original proportionally to width ratio. if (height == 0) { - height = (src_height * width + src_width / 2) / src_width; + height = + (int)(((uint64_t)src_height * width + src_width / 2) / src_width); } // Check if the overall dimensions still make sense. if (width <= 0 || height <= 0) { diff --git a/3rdparty/libwebp/utils/rescaler_utils.h b/3rdparty/libwebp/src/utils/rescaler_utils.h similarity index 96% rename from 3rdparty/libwebp/utils/rescaler_utils.h rename to 3rdparty/libwebp/src/utils/rescaler_utils.h index 98b01a76d0..8890e6fa13 100644 --- a/3rdparty/libwebp/utils/rescaler_utils.h +++ b/3rdparty/libwebp/src/utils/rescaler_utils.h @@ -11,14 +11,14 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_UTILS_RESCALER_H_ -#define WEBP_UTILS_RESCALER_H_ +#ifndef WEBP_UTILS_RESCALER_UTILS_H_ +#define WEBP_UTILS_RESCALER_UTILS_H_ #ifdef __cplusplus extern "C" { #endif -#include "../webp/types.h" +#include "src/webp/types.h" #define WEBP_RESCALER_RFIX 32 // fixed-point precision for multiplies #define WEBP_RESCALER_ONE (1ull << WEBP_RESCALER_RFIX) @@ -98,4 +98,4 @@ int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) { } // extern "C" #endif -#endif /* WEBP_UTILS_RESCALER_H_ */ +#endif /* WEBP_UTILS_RESCALER_UTILS_H_ */ diff --git a/3rdparty/libwebp/utils/thread_utils.c b/3rdparty/libwebp/src/utils/thread_utils.c similarity index 86% rename from 3rdparty/libwebp/utils/thread_utils.c rename to 3rdparty/libwebp/src/utils/thread_utils.c index 1729060c70..2052b6b006 100644 --- a/3rdparty/libwebp/utils/thread_utils.c +++ b/3rdparty/libwebp/src/utils/thread_utils.c @@ -13,8 +13,8 @@ #include #include // for memset() -#include "./thread_utils.h" -#include "./utils.h" +#include "src/utils/thread_utils.h" +#include "src/utils/utils.h" #ifdef WEBP_USE_THREAD @@ -50,11 +50,11 @@ typedef struct { #endif // _WIN32 -struct WebPWorkerImpl { +typedef struct { pthread_mutex_t mutex_; pthread_cond_t condition_; pthread_t thread_; -}; +} WebPWorkerImpl; #if defined(_WIN32) @@ -201,25 +201,24 @@ static int pthread_cond_wait(pthread_cond_t* const condition, //------------------------------------------------------------------------------ -static void Execute(WebPWorker* const worker); // Forward declaration. - static THREADFN ThreadLoop(void* ptr) { WebPWorker* const worker = (WebPWorker*)ptr; + WebPWorkerImpl* const impl = (WebPWorkerImpl*)worker->impl_; int done = 0; while (!done) { - pthread_mutex_lock(&worker->impl_->mutex_); + pthread_mutex_lock(&impl->mutex_); while (worker->status_ == OK) { // wait in idling mode - pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_); + pthread_cond_wait(&impl->condition_, &impl->mutex_); } if (worker->status_ == WORK) { - Execute(worker); + WebPGetWorkerInterface()->Execute(worker); worker->status_ = OK; } else if (worker->status_ == NOT_OK) { // finish the worker done = 1; } // signal to the main thread that we're done (for Sync()) - pthread_cond_signal(&worker->impl_->condition_); - pthread_mutex_unlock(&worker->impl_->mutex_); + pthread_cond_signal(&impl->condition_); + pthread_mutex_unlock(&impl->mutex_); } return THREAD_RETURN(NULL); // Thread is finished } @@ -229,21 +228,22 @@ static void ChangeState(WebPWorker* const worker, WebPWorkerStatus new_status) { // No-op when attempting to change state on a thread that didn't come up. // Checking status_ without acquiring the lock first would result in a data // race. - if (worker->impl_ == NULL) return; + WebPWorkerImpl* const impl = (WebPWorkerImpl*)worker->impl_; + if (impl == NULL) return; - pthread_mutex_lock(&worker->impl_->mutex_); + pthread_mutex_lock(&impl->mutex_); if (worker->status_ >= OK) { // wait for the worker to finish while (worker->status_ != OK) { - pthread_cond_wait(&worker->impl_->condition_, &worker->impl_->mutex_); + pthread_cond_wait(&impl->condition_, &impl->mutex_); } // assign new status and release the working thread if needed if (new_status != OK) { worker->status_ = new_status; - pthread_cond_signal(&worker->impl_->condition_); + pthread_cond_signal(&impl->condition_); } } - pthread_mutex_unlock(&worker->impl_->mutex_); + pthread_mutex_unlock(&impl->mutex_); } #endif // WEBP_USE_THREAD @@ -268,26 +268,28 @@ static int Reset(WebPWorker* const worker) { worker->had_error = 0; if (worker->status_ < OK) { #ifdef WEBP_USE_THREAD - worker->impl_ = (WebPWorkerImpl*)WebPSafeCalloc(1, sizeof(*worker->impl_)); + WebPWorkerImpl* const impl = + (WebPWorkerImpl*)WebPSafeCalloc(1, sizeof(WebPWorkerImpl)); + worker->impl_ = (void*)impl; if (worker->impl_ == NULL) { return 0; } - if (pthread_mutex_init(&worker->impl_->mutex_, NULL)) { + if (pthread_mutex_init(&impl->mutex_, NULL)) { goto Error; } - if (pthread_cond_init(&worker->impl_->condition_, NULL)) { - pthread_mutex_destroy(&worker->impl_->mutex_); + if (pthread_cond_init(&impl->condition_, NULL)) { + pthread_mutex_destroy(&impl->mutex_); goto Error; } - pthread_mutex_lock(&worker->impl_->mutex_); - ok = !pthread_create(&worker->impl_->thread_, NULL, ThreadLoop, worker); + pthread_mutex_lock(&impl->mutex_); + ok = !pthread_create(&impl->thread_, NULL, ThreadLoop, worker); if (ok) worker->status_ = OK; - pthread_mutex_unlock(&worker->impl_->mutex_); + pthread_mutex_unlock(&impl->mutex_); if (!ok) { - pthread_mutex_destroy(&worker->impl_->mutex_); - pthread_cond_destroy(&worker->impl_->condition_); + pthread_mutex_destroy(&impl->mutex_); + pthread_cond_destroy(&impl->condition_); Error: - WebPSafeFree(worker->impl_); + WebPSafeFree(impl); worker->impl_ = NULL; return 0; } @@ -318,11 +320,12 @@ static void Launch(WebPWorker* const worker) { static void End(WebPWorker* const worker) { #ifdef WEBP_USE_THREAD if (worker->impl_ != NULL) { + WebPWorkerImpl* const impl = (WebPWorkerImpl*)worker->impl_; ChangeState(worker, NOT_OK); - pthread_join(worker->impl_->thread_, NULL); - pthread_mutex_destroy(&worker->impl_->mutex_); - pthread_cond_destroy(&worker->impl_->condition_); - WebPSafeFree(worker->impl_); + pthread_join(impl->thread_, NULL); + pthread_mutex_destroy(&impl->mutex_); + pthread_cond_destroy(&impl->condition_); + WebPSafeFree(impl); worker->impl_ = NULL; } #else diff --git a/3rdparty/libwebp/utils/thread_utils.h b/3rdparty/libwebp/src/utils/thread_utils.h similarity index 89% rename from 3rdparty/libwebp/utils/thread_utils.h rename to 3rdparty/libwebp/src/utils/thread_utils.h index 8408311855..c8ae6c9033 100644 --- a/3rdparty/libwebp/utils/thread_utils.h +++ b/3rdparty/libwebp/src/utils/thread_utils.h @@ -11,14 +11,14 @@ // // Author: Skal (pascal.massimino@gmail.com) -#ifndef WEBP_UTILS_THREAD_H_ -#define WEBP_UTILS_THREAD_H_ +#ifndef WEBP_UTILS_THREAD_UTILS_H_ +#define WEBP_UTILS_THREAD_UTILS_H_ #ifdef HAVE_CONFIG_H -#include "../webp/config.h" +#include "src/webp/config.h" #endif -#include "../webp/types.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -35,12 +35,9 @@ typedef enum { // arguments (data1 and data2), and should return false in case of error. typedef int (*WebPWorkerHook)(void*, void*); -// Platform-dependent implementation details for the worker. -typedef struct WebPWorkerImpl WebPWorkerImpl; - // Synchronization object used to launch job in the worker thread typedef struct { - WebPWorkerImpl* impl_; + void* impl_; // platform-dependent implementation worker details WebPWorkerStatus status_; WebPWorkerHook hook; // hook to call void* data1; // first argument passed to 'hook' @@ -78,11 +75,11 @@ typedef struct { // decoding takes place. The contents of the interface struct are copied, it // is safe to free the corresponding memory after this call. This function is // not thread-safe. Return false in case of invalid pointer or methods. -WEBP_EXTERN(int) WebPSetWorkerInterface( +WEBP_EXTERN int WebPSetWorkerInterface( const WebPWorkerInterface* const winterface); // Retrieve the currently set thread worker interface. -WEBP_EXTERN(const WebPWorkerInterface*) WebPGetWorkerInterface(void); +WEBP_EXTERN const WebPWorkerInterface* WebPGetWorkerInterface(void); //------------------------------------------------------------------------------ @@ -90,4 +87,4 @@ WEBP_EXTERN(const WebPWorkerInterface*) WebPGetWorkerInterface(void); } // extern "C" #endif -#endif /* WEBP_UTILS_THREAD_H_ */ +#endif /* WEBP_UTILS_THREAD_UTILS_H_ */ diff --git a/3rdparty/libwebp/utils/utils.c b/3rdparty/libwebp/src/utils/utils.c similarity index 97% rename from 3rdparty/libwebp/utils/utils.c rename to 3rdparty/libwebp/src/utils/utils.c index 504d924b60..44d5c14f01 100644 --- a/3rdparty/libwebp/utils/utils.c +++ b/3rdparty/libwebp/src/utils/utils.c @@ -13,10 +13,11 @@ #include #include // for memcpy() -#include "../webp/decode.h" -#include "../webp/encode.h" -#include "../webp/format_constants.h" // for MAX_PALETTE_SIZE -#include "./utils.h" +#include "src/webp/decode.h" +#include "src/webp/encode.h" +#include "src/webp/format_constants.h" // for MAX_PALETTE_SIZE +#include "src/utils/color_cache_utils.h" +#include "src/utils/utils.h" // If PRINT_MEM_INFO is defined, extra info (like total memory used, number of // alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, @@ -252,7 +253,6 @@ int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { int num_colors = 0; uint8_t in_use[COLOR_HASH_SIZE] = { 0 }; uint32_t colors[COLOR_HASH_SIZE]; - static const uint64_t kHashMul = 0x1e35a7bdull; const uint32_t* argb = pic->argb; const int width = pic->width; const int height = pic->height; @@ -267,7 +267,7 @@ int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { continue; } last_pix = argb[x]; - key = ((last_pix * kHashMul) & 0xffffffffu) >> COLOR_HASH_RIGHT_SHIFT; + key = VP8LHashPix(last_pix, COLOR_HASH_RIGHT_SHIFT); while (1) { if (!in_use[key]) { colors[key] = last_pix; diff --git a/3rdparty/libwebp/utils/utils.h b/3rdparty/libwebp/src/utils/utils.h similarity index 86% rename from 3rdparty/libwebp/utils/utils.h rename to 3rdparty/libwebp/src/utils/utils.h index 3ab459050a..52921bf24e 100644 --- a/3rdparty/libwebp/utils/utils.h +++ b/3rdparty/libwebp/src/utils/utils.h @@ -16,14 +16,14 @@ #define WEBP_UTILS_UTILS_H_ #ifdef HAVE_CONFIG_H -#include "../webp/config.h" +#include "src/webp/config.h" #endif #include #include -#include "../dsp/dsp.h" -#include "../webp/types.h" +#include "src/dsp/dsp.h" +#include "src/webp/types.h" #ifdef __cplusplus extern "C" { @@ -48,13 +48,13 @@ extern "C" { // somewhere (like: malloc(num_pixels * sizeof(*something))). That's why this // safe malloc() borrows the signature from calloc(), pointing at the dangerous // underlying multiply involved. -WEBP_EXTERN(void*) WebPSafeMalloc(uint64_t nmemb, size_t size); +WEBP_EXTERN void* WebPSafeMalloc(uint64_t nmemb, size_t size); // Note that WebPSafeCalloc() expects the second argument type to be 'size_t' // in order to favor the "calloc(num_foo, sizeof(foo))" pattern. -WEBP_EXTERN(void*) WebPSafeCalloc(uint64_t nmemb, size_t size); +WEBP_EXTERN void* WebPSafeCalloc(uint64_t nmemb, size_t size); // Companion deallocation function to the above allocations. -WEBP_EXTERN(void) WebPSafeFree(void* const ptr); +WEBP_EXTERN void WebPSafeFree(void* const ptr); //------------------------------------------------------------------------------ // Alignment @@ -66,7 +66,7 @@ WEBP_EXTERN(void) WebPSafeFree(void* const ptr); // memcpy() is the safe way of moving potentially unaligned 32b memory. static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { uint32_t A; - memcpy(&A, (const int*)ptr, sizeof(A)); + memcpy(&A, ptr, sizeof(A)); return A; } static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { @@ -112,12 +112,12 @@ static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) { #define WEBP_NEED_LOG_TABLE_8BIT extern const uint8_t WebPLogTable8bit[256]; static WEBP_INLINE int WebPLog2FloorC(uint32_t n) { - int log = 0; + int log_value = 0; while (n >= 256) { - log += 8; + log_value += 8; n >>= 8; } - return log + WebPLogTable8bit[n]; + return log_value + WebPLogTable8bit[n]; } // Returns (int)floor(log2(n)). n must be > 0. @@ -147,14 +147,14 @@ static WEBP_INLINE int BitsLog2Floor(uint32_t n) { return WebPLog2FloorC(n); } struct WebPPicture; // Copy width x height pixels from 'src' to 'dst' honoring the strides. -WEBP_EXTERN(void) WebPCopyPlane(const uint8_t* src, int src_stride, - uint8_t* dst, int dst_stride, - int width, int height); +WEBP_EXTERN void WebPCopyPlane(const uint8_t* src, int src_stride, + uint8_t* dst, int dst_stride, + int width, int height); // Copy ARGB pixels from 'src' to 'dst' honoring strides. 'src' and 'dst' are // assumed to be already allocated and using ARGB data. -WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src, - struct WebPPicture* const dst); +WEBP_EXTERN void WebPCopyPixels(const struct WebPPicture* const src, + struct WebPPicture* const dst); //------------------------------------------------------------------------------ // Unique colors. @@ -166,8 +166,8 @@ WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src, // MAX_PALETTE_SIZE, also outputs the actual unique colors into 'palette'. // Note: 'palette' is assumed to be an array already allocated with at least // MAX_PALETTE_SIZE elements. -WEBP_EXTERN(int) WebPGetColorPalette(const struct WebPPicture* const pic, - uint32_t* const palette); +WEBP_EXTERN int WebPGetColorPalette(const struct WebPPicture* const pic, + uint32_t* const palette); //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/webp/decode.h b/3rdparty/libwebp/src/webp/decode.h similarity index 90% rename from 3rdparty/libwebp/webp/decode.h rename to 3rdparty/libwebp/src/webp/decode.h index 4c5e74ac36..2165e96c95 100644 --- a/3rdparty/libwebp/webp/decode.h +++ b/3rdparty/libwebp/src/webp/decode.h @@ -36,39 +36,39 @@ typedef struct WebPDecoderConfig WebPDecoderConfig; // Return the decoder's version number, packed in hexadecimal using 8bits for // each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetDecoderVersion(void); +WEBP_EXTERN int WebPGetDecoderVersion(void); // Retrieve basic header information: width, height. // This function will also validate the header, returning true on success, // false otherwise. '*width' and '*height' are only valid on successful return. // Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. -WEBP_EXTERN(int) WebPGetInfo(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_EXTERN int WebPGetInfo(const uint8_t* data, size_t data_size, + int* width, int* height); // Decodes WebP images pointed to by 'data' and returns RGBA samples, along // with the dimensions in *width and *height. The ordering of samples in // memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). // The returned pointer should be deleted calling WebPFree(). // Returns NULL in case of error. -WEBP_EXTERN(uint8_t*) WebPDecodeRGBA(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_EXTERN uint8_t* WebPDecodeRGBA(const uint8_t* data, size_t data_size, + int* width, int* height); // Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data. -WEBP_EXTERN(uint8_t*) WebPDecodeARGB(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_EXTERN uint8_t* WebPDecodeARGB(const uint8_t* data, size_t data_size, + int* width, int* height); // Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data. -WEBP_EXTERN(uint8_t*) WebPDecodeBGRA(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_EXTERN uint8_t* WebPDecodeBGRA(const uint8_t* data, size_t data_size, + int* width, int* height); // Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data. // If the bitstream contains transparency, it is ignored. -WEBP_EXTERN(uint8_t*) WebPDecodeRGB(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_EXTERN uint8_t* WebPDecodeRGB(const uint8_t* data, size_t data_size, + int* width, int* height); // Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data. -WEBP_EXTERN(uint8_t*) WebPDecodeBGR(const uint8_t* data, size_t data_size, - int* width, int* height); +WEBP_EXTERN uint8_t* WebPDecodeBGR(const uint8_t* data, size_t data_size, + int* width, int* height); // Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer @@ -80,13 +80,13 @@ WEBP_EXTERN(uint8_t*) WebPDecodeBGR(const uint8_t* data, size_t data_size, // have a common stride returned as '*uv_stride'. // Return NULL in case of error. // (*) Also named Y'CbCr. See: http://en.wikipedia.org/wiki/YCbCr -WEBP_EXTERN(uint8_t*) WebPDecodeYUV(const uint8_t* data, size_t data_size, - int* width, int* height, - uint8_t** u, uint8_t** v, - int* stride, int* uv_stride); +WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size, + int* width, int* height, + uint8_t** u, uint8_t** v, + int* stride, int* uv_stride); // Releases memory returned by the WebPDecode*() functions above. -WEBP_EXTERN(void) WebPFree(void* ptr); +WEBP_EXTERN void WebPFree(void* ptr); // These five functions are variants of the above ones, that decode the image // directly into a pre-allocated buffer 'output_buffer'. The maximum storage @@ -96,22 +96,22 @@ WEBP_EXTERN(void) WebPFree(void* ptr); // The parameter 'output_stride' specifies the distance (in bytes) // between scanlines. Hence, output_buffer_size is expected to be at least // output_stride x picture-height. -WEBP_EXTERN(uint8_t*) WebPDecodeRGBAInto( +WEBP_EXTERN uint8_t* WebPDecodeRGBAInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN(uint8_t*) WebPDecodeARGBInto( +WEBP_EXTERN uint8_t* WebPDecodeARGBInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN(uint8_t*) WebPDecodeBGRAInto( +WEBP_EXTERN uint8_t* WebPDecodeBGRAInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); // RGB and BGR variants. Here too the transparency information, if present, // will be dropped and ignored. -WEBP_EXTERN(uint8_t*) WebPDecodeRGBInto( +WEBP_EXTERN uint8_t* WebPDecodeRGBInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); -WEBP_EXTERN(uint8_t*) WebPDecodeBGRInto( +WEBP_EXTERN uint8_t* WebPDecodeBGRInto( const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); @@ -122,7 +122,7 @@ WEBP_EXTERN(uint8_t*) WebPDecodeBGRInto( // 'u_size' and 'v_size' respectively. // Pointer to the luma plane ('*luma') is returned or NULL if an error occurred // during decoding (or because some buffers were found to be too small). -WEBP_EXTERN(uint8_t*) WebPDecodeYUVInto( +WEBP_EXTERN uint8_t* WebPDecodeYUVInto( const uint8_t* data, size_t data_size, uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, @@ -213,7 +213,7 @@ struct WebPDecBuffer { }; // Internal, version-checked, entry point -WEBP_EXTERN(int) WebPInitDecBufferInternal(WebPDecBuffer*, int); +WEBP_EXTERN int WebPInitDecBufferInternal(WebPDecBuffer*, int); // Initialize the structure as empty. Must be called before any other use. // Returns false in case of version mismatch @@ -223,7 +223,7 @@ static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { // Free any memory associated with the buffer. Must always be called last. // Note: doesn't free the 'buffer' structure itself. -WEBP_EXTERN(void) WebPFreeDecBuffer(WebPDecBuffer* buffer); +WEBP_EXTERN void WebPFreeDecBuffer(WebPDecBuffer* buffer); //------------------------------------------------------------------------------ // Enumeration of the status codes @@ -277,7 +277,7 @@ typedef enum VP8StatusCode { // within valid bounds. // All other fields of WebPDecBuffer MUST remain constant between calls. // Returns NULL if the allocation failed. -WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer); +WEBP_EXTERN WebPIDecoder* WebPINewDecoder(WebPDecBuffer* output_buffer); // This function allocates and initializes an incremental-decoder object, which // will output the RGB/A samples specified by 'csp' into a preallocated @@ -289,7 +289,7 @@ WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer); // colorspace 'csp' is taken into account for allocating this buffer. All other // parameters are ignored. // Returns NULL if the allocation failed, or if some parameters are invalid. -WEBP_EXTERN(WebPIDecoder*) WebPINewRGB( +WEBP_EXTERN WebPIDecoder* WebPINewRGB( WEBP_CSP_MODE csp, uint8_t* output_buffer, size_t output_buffer_size, int output_stride); @@ -304,7 +304,7 @@ WEBP_EXTERN(WebPIDecoder*) WebPINewRGB( // In this case, the output buffer will be automatically allocated (using // MODE_YUVA) when decoding starts. All parameters are then ignored. // Returns NULL if the allocation failed or if a parameter is invalid. -WEBP_EXTERN(WebPIDecoder*) WebPINewYUVA( +WEBP_EXTERN WebPIDecoder* WebPINewYUVA( uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, uint8_t* v, size_t v_size, int v_stride, @@ -312,19 +312,19 @@ WEBP_EXTERN(WebPIDecoder*) WebPINewYUVA( // Deprecated version of the above, without the alpha plane. // Kept for backward compatibility. -WEBP_EXTERN(WebPIDecoder*) WebPINewYUV( +WEBP_EXTERN WebPIDecoder* WebPINewYUV( uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, uint8_t* v, size_t v_size, int v_stride); // Deletes the WebPIDecoder object and associated memory. Must always be called // if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded. -WEBP_EXTERN(void) WebPIDelete(WebPIDecoder* idec); +WEBP_EXTERN void WebPIDelete(WebPIDecoder* idec); // Copies and decodes the next available data. Returns VP8_STATUS_OK when // the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more // data is expected. Returns error in other cases. -WEBP_EXTERN(VP8StatusCode) WebPIAppend( +WEBP_EXTERN VP8StatusCode WebPIAppend( WebPIDecoder* idec, const uint8_t* data, size_t data_size); // A variant of the above function to be used when data buffer contains @@ -332,7 +332,7 @@ WEBP_EXTERN(VP8StatusCode) WebPIAppend( // to the internal memory. // Note that the value of the 'data' pointer can change between calls to // WebPIUpdate, for instance when the data buffer is resized to fit larger data. -WEBP_EXTERN(VP8StatusCode) WebPIUpdate( +WEBP_EXTERN VP8StatusCode WebPIUpdate( WebPIDecoder* idec, const uint8_t* data, size_t data_size); // Returns the RGB/A image decoded so far. Returns NULL if output params @@ -340,15 +340,16 @@ WEBP_EXTERN(VP8StatusCode) WebPIUpdate( // specified during call to WebPINewDecoder() or WebPINewRGB(). // *last_y is the index of last decoded row in raster scan order. Some pointers // (*last_y, *width etc.) can be NULL if corresponding information is not -// needed. -WEBP_EXTERN(uint8_t*) WebPIDecGetRGB( +// needed. The values in these pointers are only valid on successful (non-NULL) +// return. +WEBP_EXTERN uint8_t* WebPIDecGetRGB( const WebPIDecoder* idec, int* last_y, int* width, int* height, int* stride); // Same as above function to get a YUVA image. Returns pointer to the luma // plane or NULL in case of error. If there is no alpha information // the alpha pointer '*a' will be returned NULL. -WEBP_EXTERN(uint8_t*) WebPIDecGetYUVA( +WEBP_EXTERN uint8_t* WebPIDecGetYUVA( const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, uint8_t** a, int* width, int* height, int* stride, int* uv_stride, int* a_stride); @@ -368,7 +369,7 @@ static WEBP_INLINE uint8_t* WebPIDecGetYUV( // Returns NULL in case the incremental decoder object is in an invalid state. // Otherwise returns the pointer to the internal representation. This structure // is read-only, tied to WebPIDecoder's lifespan and should not be modified. -WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea( +WEBP_EXTERN const WebPDecBuffer* WebPIDecodedArea( const WebPIDecoder* idec, int* left, int* top, int* width, int* height); //------------------------------------------------------------------------------ @@ -416,7 +417,7 @@ struct WebPBitstreamFeatures { }; // Internal, version-checked, entry point -WEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal( +WEBP_EXTERN VP8StatusCode WebPGetFeaturesInternal( const uint8_t*, size_t, WebPBitstreamFeatures*, int); // Retrieve features from the bitstream. The *features structure is filled @@ -457,7 +458,7 @@ struct WebPDecoderConfig { }; // Internal, version-checked, entry point -WEBP_EXTERN(int) WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); +WEBP_EXTERN int WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); // Initialize the configuration as empty. This function must always be // called first, unless WebPGetFeatures() is to be called. @@ -477,14 +478,14 @@ static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { // The return WebPIDecoder object must always be deleted calling WebPIDelete(). // Returns NULL in case of error (and config->status will then reflect // the error condition, if available). -WEBP_EXTERN(WebPIDecoder*) WebPIDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config); +WEBP_EXTERN WebPIDecoder* WebPIDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config); // Non-incremental version. This version decodes the full data at once, taking // 'config' into account. Returns decoding status (which should be VP8_STATUS_OK // if the decoding was successful). Note that 'config' cannot be NULL. -WEBP_EXTERN(VP8StatusCode) WebPDecode(const uint8_t* data, size_t data_size, - WebPDecoderConfig* config); +WEBP_EXTERN VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, + WebPDecoderConfig* config); #ifdef __cplusplus } // extern "C" diff --git a/3rdparty/libwebp/webp/demux.h b/3rdparty/libwebp/src/webp/demux.h similarity index 85% rename from 3rdparty/libwebp/webp/demux.h rename to 3rdparty/libwebp/src/webp/demux.h index 454f6914b2..555d641338 100644 --- a/3rdparty/libwebp/webp/demux.h +++ b/3rdparty/libwebp/src/webp/demux.h @@ -71,7 +71,7 @@ typedef struct WebPAnimDecoderOptions WebPAnimDecoderOptions; // Returns the version number of the demux library, packed in hexadecimal using // 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetDemuxVersion(void); +WEBP_EXTERN int WebPGetDemuxVersion(void); //------------------------------------------------------------------------------ // Life of a Demux object @@ -85,7 +85,7 @@ typedef enum WebPDemuxState { } WebPDemuxState; // Internal, version-checked, entry point -WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal( +WEBP_EXTERN WebPDemuxer* WebPDemuxInternal( const WebPData*, int, WebPDemuxState*, int); // Parses the full WebP file given by 'data'. For single images the WebP file @@ -109,27 +109,32 @@ static WEBP_INLINE WebPDemuxer* WebPDemuxPartial( } // Frees memory associated with 'dmux'. -WEBP_EXTERN(void) WebPDemuxDelete(WebPDemuxer* dmux); +WEBP_EXTERN void WebPDemuxDelete(WebPDemuxer* dmux); //------------------------------------------------------------------------------ // Data/information extraction. typedef enum WebPFormatFeature { - WEBP_FF_FORMAT_FLAGS, // Extended format flags present in the 'VP8X' chunk. + WEBP_FF_FORMAT_FLAGS, // bit-wise combination of WebPFeatureFlags + // corresponding to the 'VP8X' chunk (if present). WEBP_FF_CANVAS_WIDTH, WEBP_FF_CANVAS_HEIGHT, - WEBP_FF_LOOP_COUNT, - WEBP_FF_BACKGROUND_COLOR, - WEBP_FF_FRAME_COUNT // Number of frames present in the demux object. - // In case of a partial demux, this is the number of - // frames seen so far, with the last frame possibly - // being partial. + WEBP_FF_LOOP_COUNT, // only relevant for animated file + WEBP_FF_BACKGROUND_COLOR, // idem. + WEBP_FF_FRAME_COUNT // Number of frames present in the demux object. + // In case of a partial demux, this is the number + // of frames seen so far, with the last frame + // possibly being partial. } WebPFormatFeature; // Get the 'feature' value from the 'dmux'. // NOTE: values are only valid if WebPDemux() was used or WebPDemuxPartial() // returned a state > WEBP_DEMUX_PARSING_HEADER. -WEBP_EXTERN(uint32_t) WebPDemuxGetI( +// If 'feature' is WEBP_FF_FORMAT_FLAGS, the returned value is a bit-wise +// combination of WebPFeatureFlags values. +// If 'feature' is WEBP_FF_LOOP_COUNT, WEBP_FF_BACKGROUND_COLOR, the returned +// value is only meaningful if the bitstream is animated. +WEBP_EXTERN uint32_t WebPDemuxGetI( const WebPDemuxer* dmux, WebPFormatFeature feature); //------------------------------------------------------------------------------ @@ -159,20 +164,20 @@ struct WebPIterator { // Returns false if 'dmux' is NULL or frame 'frame_number' is not present. // Call WebPDemuxReleaseIterator() when use of the iterator is complete. // NOTE: 'dmux' must persist for the lifetime of 'iter'. -WEBP_EXTERN(int) WebPDemuxGetFrame( +WEBP_EXTERN int WebPDemuxGetFrame( const WebPDemuxer* dmux, int frame_number, WebPIterator* iter); // Sets 'iter->fragment' to point to the next ('iter->frame_num' + 1) or // previous ('iter->frame_num' - 1) frame. These functions do not loop. // Returns true on success, false otherwise. -WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter); -WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter); +WEBP_EXTERN int WebPDemuxNextFrame(WebPIterator* iter); +WEBP_EXTERN int WebPDemuxPrevFrame(WebPIterator* iter); // Releases any memory associated with 'iter'. // Must be called before any subsequent calls to WebPDemuxGetChunk() on the same // iter. Also, must be called before destroying the associated WebPDemuxer with // WebPDemuxDelete(). -WEBP_EXTERN(void) WebPDemuxReleaseIterator(WebPIterator* iter); +WEBP_EXTERN void WebPDemuxReleaseIterator(WebPIterator* iter); //------------------------------------------------------------------------------ // Chunk iteration. @@ -197,20 +202,20 @@ struct WebPChunkIterator { // payloads are accessed through WebPDemuxGetFrame() and related functions. // Call WebPDemuxReleaseChunkIterator() when use of the iterator is complete. // NOTE: 'dmux' must persist for the lifetime of the iterator. -WEBP_EXTERN(int) WebPDemuxGetChunk(const WebPDemuxer* dmux, - const char fourcc[4], int chunk_number, - WebPChunkIterator* iter); +WEBP_EXTERN int WebPDemuxGetChunk(const WebPDemuxer* dmux, + const char fourcc[4], int chunk_number, + WebPChunkIterator* iter); // Sets 'iter->chunk' to point to the next ('iter->chunk_num' + 1) or previous // ('iter->chunk_num' - 1) chunk. These functions do not loop. // Returns true on success, false otherwise. -WEBP_EXTERN(int) WebPDemuxNextChunk(WebPChunkIterator* iter); -WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter); +WEBP_EXTERN int WebPDemuxNextChunk(WebPChunkIterator* iter); +WEBP_EXTERN int WebPDemuxPrevChunk(WebPChunkIterator* iter); // Releases any memory associated with 'iter'. // Must be called before destroying the associated WebPDemuxer with // WebPDemuxDelete(). -WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); +WEBP_EXTERN void WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); //------------------------------------------------------------------------------ // WebPAnimDecoder API @@ -252,7 +257,7 @@ struct WebPAnimDecoderOptions { }; // Internal, version-checked, entry point. -WEBP_EXTERN(int) WebPAnimDecoderOptionsInitInternal( +WEBP_EXTERN int WebPAnimDecoderOptionsInitInternal( WebPAnimDecoderOptions*, int); // Should always be called, to initialize a fresh WebPAnimDecoderOptions @@ -266,7 +271,7 @@ static WEBP_INLINE int WebPAnimDecoderOptionsInit( } // Internal, version-checked, entry point. -WEBP_EXTERN(WebPAnimDecoder*) WebPAnimDecoderNewInternal( +WEBP_EXTERN WebPAnimDecoder* WebPAnimDecoderNewInternal( const WebPData*, const WebPAnimDecoderOptions*, int); // Creates and initializes a WebPAnimDecoder object. @@ -301,8 +306,8 @@ struct WebPAnimInfo { // info - (out) global information fetched from the animation. // Returns: // True on success. -WEBP_EXTERN(int) WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, - WebPAnimInfo* info); +WEBP_EXTERN int WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, + WebPAnimInfo* info); // Fetch the next frame from 'dec' based on options supplied to // WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size @@ -316,8 +321,8 @@ WEBP_EXTERN(int) WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, // Returns: // False if any of the arguments are NULL, or if there is a parsing or // decoding error, or if there are no more frames. Otherwise, returns true. -WEBP_EXTERN(int) WebPAnimDecoderGetNext(WebPAnimDecoder* dec, - uint8_t** buf, int* timestamp); +WEBP_EXTERN int WebPAnimDecoderGetNext(WebPAnimDecoder* dec, + uint8_t** buf, int* timestamp); // Check if there are more frames left to decode. // Parameters: @@ -325,7 +330,7 @@ WEBP_EXTERN(int) WebPAnimDecoderGetNext(WebPAnimDecoder* dec, // Returns: // True if 'dec' is not NULL and some frames are yet to be decoded. // Otherwise, returns false. -WEBP_EXTERN(int) WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec); +WEBP_EXTERN int WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec); // Resets the WebPAnimDecoder object, so that next call to // WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be @@ -333,7 +338,7 @@ WEBP_EXTERN(int) WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec); // info.loop_count times) without destroying and recreating the 'dec' object. // Parameters: // dec - (in/out) decoder instance to be reset -WEBP_EXTERN(void) WebPAnimDecoderReset(WebPAnimDecoder* dec); +WEBP_EXTERN void WebPAnimDecoderReset(WebPAnimDecoder* dec); // Grab the internal demuxer object. // Getting the demuxer object can be useful if one wants to use operations only @@ -343,13 +348,13 @@ WEBP_EXTERN(void) WebPAnimDecoderReset(WebPAnimDecoder* dec); // // Parameters: // dec - (in) decoder instance from which the demuxer object is to be fetched. -WEBP_EXTERN(const WebPDemuxer*) WebPAnimDecoderGetDemuxer( +WEBP_EXTERN const WebPDemuxer* WebPAnimDecoderGetDemuxer( const WebPAnimDecoder* dec); // Deletes the WebPAnimDecoder object. // Parameters: // dec - (in/out) decoder instance to be deleted -WEBP_EXTERN(void) WebPAnimDecoderDelete(WebPAnimDecoder* dec); +WEBP_EXTERN void WebPAnimDecoderDelete(WebPAnimDecoder* dec); #ifdef __cplusplus } // extern "C" diff --git a/3rdparty/libwebp/webp/encode.h b/3rdparty/libwebp/src/webp/encode.h similarity index 84% rename from 3rdparty/libwebp/webp/encode.h rename to 3rdparty/libwebp/src/webp/encode.h index 35fde1d052..7ec3543dc2 100644 --- a/3rdparty/libwebp/webp/encode.h +++ b/3rdparty/libwebp/src/webp/encode.h @@ -35,7 +35,7 @@ typedef struct WebPMemoryWriter WebPMemoryWriter; // Return the encoder's version number, packed in hexadecimal using 8bits for // each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetEncoderVersion(void); +WEBP_EXTERN int WebPGetEncoderVersion(void); //------------------------------------------------------------------------------ // One-stop-shop call! No questions asked: @@ -46,37 +46,37 @@ WEBP_EXTERN(int) WebPGetEncoderVersion(void); // These functions compress using the lossy format, and the quality_factor // can go from 0 (smaller output, lower quality) to 100 (best quality, // larger output). -WEBP_EXTERN(size_t) WebPEncodeRGB(const uint8_t* rgb, +WEBP_EXTERN size_t WebPEncodeRGB(const uint8_t* rgb, + int width, int height, int stride, + float quality_factor, uint8_t** output); +WEBP_EXTERN size_t WebPEncodeBGR(const uint8_t* bgr, + int width, int height, int stride, + float quality_factor, uint8_t** output); +WEBP_EXTERN size_t WebPEncodeRGBA(const uint8_t* rgba, int width, int height, int stride, float quality_factor, uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeBGR(const uint8_t* bgr, +WEBP_EXTERN size_t WebPEncodeBGRA(const uint8_t* bgra, int width, int height, int stride, float quality_factor, uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeRGBA(const uint8_t* rgba, - int width, int height, int stride, - float quality_factor, uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeBGRA(const uint8_t* bgra, - int width, int height, int stride, - float quality_factor, uint8_t** output); // These functions are the equivalent of the above, but compressing in a // lossless manner. Files are usually larger than lossy format, but will // not suffer any compression loss. -WEBP_EXTERN(size_t) WebPEncodeLosslessRGB(const uint8_t* rgb, +WEBP_EXTERN size_t WebPEncodeLosslessRGB(const uint8_t* rgb, + int width, int height, int stride, + uint8_t** output); +WEBP_EXTERN size_t WebPEncodeLosslessBGR(const uint8_t* bgr, + int width, int height, int stride, + uint8_t** output); +WEBP_EXTERN size_t WebPEncodeLosslessRGBA(const uint8_t* rgba, int width, int height, int stride, uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeLosslessBGR(const uint8_t* bgr, +WEBP_EXTERN size_t WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height, int stride, uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeLosslessRGBA(const uint8_t* rgba, - int width, int height, int stride, - uint8_t** output); -WEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra, - int width, int height, int stride, - uint8_t** output); // Releases memory returned by the WebPEncode*() functions above. -WEBP_EXTERN(void) WebPFree(void* ptr); +WEBP_EXTERN void WebPFree(void* ptr); //------------------------------------------------------------------------------ // Coding parameters @@ -93,12 +93,15 @@ typedef enum WebPImageHint { // Compression parameters. struct WebPConfig { int lossless; // Lossless encoding (0=lossy(default), 1=lossless). - float quality; // between 0 (smallest file) and 100 (biggest) + float quality; // between 0 and 100. For lossy, 0 gives the smallest + // size and 100 the largest. For lossless, this + // parameter is the amount of effort put into the + // compression: 0 is the fastest but gives larger + // files compared to the slowest, but best, 100. int method; // quality/speed trade-off (0=fast, 6=slower-better) WebPImageHint image_hint; // Hint for image type (lossless only for now). - // Parameters related to lossy compression only: int target_size; // if non-zero, set the desired target size in bytes. // Takes precedence over the 'compression' parameter. float target_PSNR; // if non-zero, specifies the minimal distortion to @@ -159,7 +162,7 @@ typedef enum WebPPreset { } WebPPreset; // Internal, version-checked, entry point -WEBP_EXTERN(int) WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int); +WEBP_EXTERN int WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int); // Should always be called, to initialize a fresh WebPConfig structure before // modification. Returns false in case of version mismatch. WebPConfigInit() @@ -186,15 +189,15 @@ static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, // speed and final compressed size. // This function will overwrite several fields from config: 'method', 'quality' // and 'lossless'. Returns false in case of parameter error. -WEBP_EXTERN(int) WebPConfigLosslessPreset(WebPConfig* config, int level); +WEBP_EXTERN int WebPConfigLosslessPreset(WebPConfig* config, int level); // Returns true if 'config' is non-NULL and all configuration parameters are // within their valid ranges. -WEBP_EXTERN(int) WebPValidateConfig(const WebPConfig* config); +WEBP_EXTERN int WebPValidateConfig(const WebPConfig* config); //------------------------------------------------------------------------------ // Input / Output -// Structure for storing auxiliary statistics (mostly for lossy encoding). +// Structure for storing auxiliary statistics. struct WebPAuxStats { int coded_size; // final size @@ -242,16 +245,16 @@ struct WebPMemoryWriter { }; // The following must be called first before any use. -WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer); +WEBP_EXTERN void WebPMemoryWriterInit(WebPMemoryWriter* writer); // The following must be called to deallocate writer->mem memory. The 'writer' // object itself is not deallocated. -WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer); +WEBP_EXTERN void WebPMemoryWriterClear(WebPMemoryWriter* writer); // The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon // completion, writer.mem and writer.size will hold the coded data. // writer.mem must be freed by calling WebPMemoryWriterClear. -WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size, - const WebPPicture* picture); +WEBP_EXTERN int WebPMemoryWrite(const uint8_t* data, size_t data_size, + const WebPPicture* picture); // Progress hook, called from time to time to report progress. It can return // false to request an abort of the encoding process, or true otherwise if @@ -354,7 +357,7 @@ struct WebPPicture { }; // Internal, version-checked, entry point -WEBP_EXTERN(int) WebPPictureInitInternal(WebPPicture*, int); +WEBP_EXTERN int WebPPictureInitInternal(WebPPicture*, int); // Should always be called, to initialize the structure. Returns false in case // of version mismatch. WebPPictureInit() must have succeeded before using the @@ -371,20 +374,20 @@ static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { // Allocate y/u/v buffers as per colorspace/width/height specification. // Note! This function will free the previous buffer if needed. // Returns false in case of memory error. -WEBP_EXTERN(int) WebPPictureAlloc(WebPPicture* picture); +WEBP_EXTERN int WebPPictureAlloc(WebPPicture* picture); // Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*(). // Note that this function does _not_ free the memory used by the 'picture' // object itself. // Besides memory (which is reclaimed) all other fields of 'picture' are // preserved. -WEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture); +WEBP_EXTERN void WebPPictureFree(WebPPicture* picture); // Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst // will fully own the copied pixels (this is not a view). The 'dst' picture need // not be initialized as its content is overwritten. // Returns false in case of memory allocation error. -WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); +WEBP_EXTERN int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); // Compute the single distortion for packed planes of samples. // 'src' will be compared to 'ref', and the raw distortion stored into @@ -393,19 +396,19 @@ WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); // 'x_step' is the horizontal stride (in bytes) between samples. // 'src/ref_stride' is the byte distance between rows. // Returns false in case of error (bad parameter, memory allocation error, ...). -WEBP_EXTERN(int) WebPPlaneDistortion(const uint8_t* src, size_t src_stride, - const uint8_t* ref, size_t ref_stride, - int width, int height, - size_t x_step, - int type, // 0 = PSNR, 1 = SSIM, 2 = LSIM - float* distortion, float* result); +WEBP_EXTERN int WebPPlaneDistortion(const uint8_t* src, size_t src_stride, + const uint8_t* ref, size_t ref_stride, + int width, int height, + size_t x_step, + int type, // 0 = PSNR, 1 = SSIM, 2 = LSIM + float* distortion, float* result); // Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results // are in dB, stored in result[] in the B/G/R/A/All order. The distortion is // always performed using ARGB samples. Hence if the input is YUV(A), the // picture will be internally converted to ARGB (just for the measurement). // Warning: this function is rather CPU-intensive. -WEBP_EXTERN(int) WebPPictureDistortion( +WEBP_EXTERN int WebPPictureDistortion( const WebPPicture* src, const WebPPicture* ref, int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM float result[5]); @@ -418,8 +421,8 @@ WEBP_EXTERN(int) WebPPictureDistortion( // must be fully be comprised inside the 'src' source picture. If the source // picture uses the YUV420 colorspace, the top and left coordinates will be // snapped to even values. -WEBP_EXTERN(int) WebPPictureCrop(WebPPicture* picture, - int left, int top, int width, int height); +WEBP_EXTERN int WebPPictureCrop(WebPPicture* picture, + int left, int top, int width, int height); // Extracts a view from 'src' picture into 'dst'. The rectangle for the view // is defined by the top-left corner pixel coordinates (left, top) as well @@ -432,42 +435,42 @@ WEBP_EXTERN(int) WebPPictureCrop(WebPPicture* picture, // with WebPPictureInit() if it is different from 'src', since its content will // be overwritten. // Returns false in case of memory allocation error or invalid parameters. -WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src, - int left, int top, int width, int height, - WebPPicture* dst); +WEBP_EXTERN int WebPPictureView(const WebPPicture* src, + int left, int top, int width, int height, + WebPPicture* dst); // Returns true if the 'picture' is actually a view and therefore does // not own the memory for pixels. -WEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture); +WEBP_EXTERN int WebPPictureIsView(const WebPPicture* picture); // Rescale a picture to new dimension width x height. // If either 'width' or 'height' (but not both) is 0 the corresponding // dimension will be calculated preserving the aspect ratio. // No gamma correction is applied. // Returns false in case of error (invalid parameter or insufficient memory). -WEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height); +WEBP_EXTERN int WebPPictureRescale(WebPPicture* pic, int width, int height); // Colorspace conversion function to import RGB samples. // Previous buffer will be free'd, if any. // *rgb buffer should have a size of at least height * rgb_stride. // Returns false in case of memory error. -WEBP_EXTERN(int) WebPPictureImportRGB( +WEBP_EXTERN int WebPPictureImportRGB( WebPPicture* picture, const uint8_t* rgb, int rgb_stride); // Same, but for RGBA buffer. -WEBP_EXTERN(int) WebPPictureImportRGBA( +WEBP_EXTERN int WebPPictureImportRGBA( WebPPicture* picture, const uint8_t* rgba, int rgba_stride); // Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format // input buffer ignoring the alpha channel. Avoids needing to copy the data // to a temporary 24-bit RGB buffer to import the RGB only. -WEBP_EXTERN(int) WebPPictureImportRGBX( +WEBP_EXTERN int WebPPictureImportRGBX( WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride); // Variants of the above, but taking BGR(A|X) input. -WEBP_EXTERN(int) WebPPictureImportBGR( +WEBP_EXTERN int WebPPictureImportBGR( WebPPicture* picture, const uint8_t* bgr, int bgr_stride); -WEBP_EXTERN(int) WebPPictureImportBGRA( +WEBP_EXTERN int WebPPictureImportBGRA( WebPPicture* picture, const uint8_t* bgra, int bgra_stride); -WEBP_EXTERN(int) WebPPictureImportBGRX( +WEBP_EXTERN int WebPPictureImportBGRX( WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride); // Converts picture->argb data to the YUV420A format. The 'colorspace' @@ -476,14 +479,14 @@ WEBP_EXTERN(int) WebPPictureImportBGRX( // non-opaque transparent values is detected, and 'colorspace' will be // adjusted accordingly. Note that this method is lossy. // Returns false in case of error. -WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture, - WebPEncCSP /*colorspace = WEBP_YUV420*/); +WEBP_EXTERN int WebPPictureARGBToYUVA(WebPPicture* picture, + WebPEncCSP /*colorspace = WEBP_YUV420*/); // Same as WebPPictureARGBToYUVA(), but the conversion is done using // pseudo-random dithering with a strength 'dithering' between // 0.0 (no dithering) and 1.0 (maximum dithering). This is useful // for photographic picture. -WEBP_EXTERN(int) WebPPictureARGBToYUVADithered( +WEBP_EXTERN int WebPPictureARGBToYUVADithered( WebPPicture* picture, WebPEncCSP colorspace, float dithering); // Performs 'sharp' RGBA->YUVA420 downsampling and colorspace conversion. @@ -491,9 +494,9 @@ WEBP_EXTERN(int) WebPPictureARGBToYUVADithered( // method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better // and sharper YUV representation. // Returns false in case of error. -WEBP_EXTERN(int) WebPPictureSharpARGBToYUVA(WebPPicture* picture); +WEBP_EXTERN int WebPPictureSharpARGBToYUVA(WebPPicture* picture); // kept for backward compatibility: -WEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture); +WEBP_EXTERN int WebPPictureSmartARGBToYUVA(WebPPicture* picture); // Converts picture->yuv to picture->argb and sets picture->use_argb to true. // The input format must be YUV_420 or YUV_420A. The conversion from YUV420 to @@ -501,22 +504,22 @@ WEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture); // Note that the use of this colorspace is discouraged if one has access to the // raw ARGB samples, since using YUV420 is comparatively lossy. // Returns false in case of error. -WEBP_EXTERN(int) WebPPictureYUVAToARGB(WebPPicture* picture); +WEBP_EXTERN int WebPPictureYUVAToARGB(WebPPicture* picture); // Helper function: given a width x height plane of RGBA or YUV(A) samples -// clean-up the YUV or RGB samples under fully transparent area, to help -// compressibility (no guarantee, though). -WEBP_EXTERN(void) WebPCleanupTransparentArea(WebPPicture* picture); +// clean-up or smoothen the YUV or RGB samples under fully transparent area, +// to help compressibility (no guarantee, though). +WEBP_EXTERN void WebPCleanupTransparentArea(WebPPicture* picture); // Scan the picture 'picture' for the presence of non fully opaque alpha values. // Returns true in such case. Otherwise returns false (indicating that the // alpha plane can be ignored altogether e.g.). -WEBP_EXTERN(int) WebPPictureHasTransparency(const WebPPicture* picture); +WEBP_EXTERN int WebPPictureHasTransparency(const WebPPicture* picture); // Remove the transparency information (if present) by blending the color with // the background color 'background_rgb' (specified as 24bit RGB triplet). // After this call, all alpha values are reset to 0xff. -WEBP_EXTERN(void) WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb); +WEBP_EXTERN void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb); //------------------------------------------------------------------------------ // Main call @@ -531,7 +534,7 @@ WEBP_EXTERN(void) WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb); // the former for lossy encoding, and the latter for lossless encoding // (when config.lossless is true). Automatic conversion from one format to // another is provided but they both incur some loss. -WEBP_EXTERN(int) WebPEncode(const WebPConfig* config, WebPPicture* picture); +WEBP_EXTERN int WebPEncode(const WebPConfig* config, WebPPicture* picture); //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/webp/format_constants.h b/3rdparty/libwebp/src/webp/format_constants.h similarity index 100% rename from 3rdparty/libwebp/webp/format_constants.h rename to 3rdparty/libwebp/src/webp/format_constants.h diff --git a/3rdparty/libwebp/webp/mux.h b/3rdparty/libwebp/src/webp/mux.h similarity index 92% rename from 3rdparty/libwebp/webp/mux.h rename to 3rdparty/libwebp/src/webp/mux.h index daccc65e86..28bb4a41c9 100644 --- a/3rdparty/libwebp/webp/mux.h +++ b/3rdparty/libwebp/src/webp/mux.h @@ -98,13 +98,13 @@ typedef enum WebPChunkId { // Returns the version number of the mux library, packed in hexadecimal using // 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. -WEBP_EXTERN(int) WebPGetMuxVersion(void); +WEBP_EXTERN int WebPGetMuxVersion(void); //------------------------------------------------------------------------------ // Life of a Mux object // Internal, version-checked, entry point -WEBP_EXTERN(WebPMux*) WebPNewInternal(int); +WEBP_EXTERN WebPMux* WebPNewInternal(int); // Creates an empty mux object. // Returns: @@ -117,13 +117,13 @@ static WEBP_INLINE WebPMux* WebPMuxNew(void) { // Deletes the mux object. // Parameters: // mux - (in/out) object to be deleted -WEBP_EXTERN(void) WebPMuxDelete(WebPMux* mux); +WEBP_EXTERN void WebPMuxDelete(WebPMux* mux); //------------------------------------------------------------------------------ // Mux creation. // Internal, version-checked, entry point -WEBP_EXTERN(WebPMux*) WebPMuxCreateInternal(const WebPData*, int, int); +WEBP_EXTERN WebPMux* WebPMuxCreateInternal(const WebPData*, int, int); // Creates a mux object from raw data given in WebP RIFF format. // Parameters: @@ -160,7 +160,7 @@ static WEBP_INLINE WebPMux* WebPMuxCreate(const WebPData* bitstream, // or if fourcc corresponds to an image chunk. // WEBP_MUX_MEMORY_ERROR - on memory allocation error. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetChunk( +WEBP_EXTERN WebPMuxError WebPMuxSetChunk( WebPMux* mux, const char fourcc[4], const WebPData* chunk_data, int copy_data); @@ -176,7 +176,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxSetChunk( // or if fourcc corresponds to an image chunk. // WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given id. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetChunk( +WEBP_EXTERN WebPMuxError WebPMuxGetChunk( const WebPMux* mux, const char fourcc[4], WebPData* chunk_data); // Deletes the chunk with the given 'fourcc' from the mux object. @@ -189,7 +189,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxGetChunk( // or if fourcc corresponds to an image chunk. // WEBP_MUX_NOT_FOUND - If mux does not contain a chunk with the given fourcc. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteChunk( +WEBP_EXTERN WebPMuxError WebPMuxDeleteChunk( WebPMux* mux, const char fourcc[4]); //------------------------------------------------------------------------------ @@ -222,7 +222,7 @@ struct WebPMuxFrameInfo { // WEBP_MUX_INVALID_ARGUMENT - if mux is NULL or bitstream is NULL. // WEBP_MUX_MEMORY_ERROR - on memory allocation error. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetImage( +WEBP_EXTERN WebPMuxError WebPMuxSetImage( WebPMux* mux, const WebPData* bitstream, int copy_data); // Adds a frame at the end of the mux object. @@ -241,7 +241,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxSetImage( // or if content of 'frame' is invalid. // WEBP_MUX_MEMORY_ERROR - on memory allocation error. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame( +WEBP_EXTERN WebPMuxError WebPMuxPushFrame( WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data); // Gets the nth frame from the mux object. @@ -259,7 +259,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxPushFrame( // WEBP_MUX_BAD_DATA - if nth frame chunk in mux is invalid. // WEBP_MUX_MEMORY_ERROR - on memory allocation error. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetFrame( +WEBP_EXTERN WebPMuxError WebPMuxGetFrame( const WebPMux* mux, uint32_t nth, WebPMuxFrameInfo* frame); // Deletes a frame from the mux object. @@ -272,7 +272,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxGetFrame( // WEBP_MUX_NOT_FOUND - If there are less than nth frames in the mux object // before deletion. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth); +WEBP_EXTERN WebPMuxError WebPMuxDeleteFrame(WebPMux* mux, uint32_t nth); //------------------------------------------------------------------------------ // Animation. @@ -296,7 +296,7 @@ struct WebPMuxAnimParams { // WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. // WEBP_MUX_MEMORY_ERROR - on memory allocation error. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetAnimationParams( +WEBP_EXTERN WebPMuxError WebPMuxSetAnimationParams( WebPMux* mux, const WebPMuxAnimParams* params); // Gets the animation parameters from the mux object. @@ -307,7 +307,7 @@ WEBP_EXTERN(WebPMuxError) WebPMuxSetAnimationParams( // WEBP_MUX_INVALID_ARGUMENT - if mux or params is NULL. // WEBP_MUX_NOT_FOUND - if ANIM chunk is not present in mux object. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetAnimationParams( +WEBP_EXTERN WebPMuxError WebPMuxGetAnimationParams( const WebPMux* mux, WebPMuxAnimParams* params); //------------------------------------------------------------------------------ @@ -328,8 +328,8 @@ WEBP_EXTERN(WebPMuxError) WebPMuxGetAnimationParams( // WEBP_MUX_INVALID_ARGUMENT - if mux is NULL; or // width or height are invalid or out of bounds // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxSetCanvasSize(WebPMux* mux, - int width, int height); +WEBP_EXTERN WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux, + int width, int height); // Gets the canvas size from the mux object. // Note: This method assumes that the VP8X chunk, if present, is up-to-date. @@ -343,8 +343,8 @@ WEBP_EXTERN(WebPMuxError) WebPMuxSetCanvasSize(WebPMux* mux, // WEBP_MUX_INVALID_ARGUMENT - if mux, width or height is NULL. // WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetCanvasSize(const WebPMux* mux, - int* width, int* height); +WEBP_EXTERN WebPMuxError WebPMuxGetCanvasSize(const WebPMux* mux, + int* width, int* height); // Gets the feature flags from the mux object. // Note: This method assumes that the VP8X chunk, if present, is up-to-date. @@ -359,8 +359,8 @@ WEBP_EXTERN(WebPMuxError) WebPMuxGetCanvasSize(const WebPMux* mux, // WEBP_MUX_INVALID_ARGUMENT - if mux or flags is NULL. // WEBP_MUX_BAD_DATA - if VP8X/VP8/VP8L chunk or canvas size is invalid. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxGetFeatures(const WebPMux* mux, - uint32_t* flags); +WEBP_EXTERN WebPMuxError WebPMuxGetFeatures(const WebPMux* mux, + uint32_t* flags); // Gets number of chunks with the given 'id' in the mux object. // Parameters: @@ -370,8 +370,8 @@ WEBP_EXTERN(WebPMuxError) WebPMuxGetFeatures(const WebPMux* mux, // Returns: // WEBP_MUX_INVALID_ARGUMENT - if mux, or num_elements is NULL. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux, - WebPChunkId id, int* num_elements); +WEBP_EXTERN WebPMuxError WebPMuxNumChunks(const WebPMux* mux, + WebPChunkId id, int* num_elements); // Assembles all chunks in WebP RIFF format and returns in 'assembled_data'. // This function also validates the mux object. @@ -388,8 +388,8 @@ WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux, // WEBP_MUX_INVALID_ARGUMENT - if mux or assembled_data is NULL. // WEBP_MUX_MEMORY_ERROR - on memory allocation error. // WEBP_MUX_OK - on success. -WEBP_EXTERN(WebPMuxError) WebPMuxAssemble(WebPMux* mux, - WebPData* assembled_data); +WEBP_EXTERN WebPMuxError WebPMuxAssemble(WebPMux* mux, + WebPData* assembled_data); //------------------------------------------------------------------------------ // WebPAnimEncoder API @@ -442,7 +442,7 @@ struct WebPAnimEncoderOptions { }; // Internal, version-checked, entry point. -WEBP_EXTERN(int) WebPAnimEncoderOptionsInitInternal( +WEBP_EXTERN int WebPAnimEncoderOptionsInitInternal( WebPAnimEncoderOptions*, int); // Should always be called, to initialize a fresh WebPAnimEncoderOptions @@ -455,7 +455,7 @@ static WEBP_INLINE int WebPAnimEncoderOptionsInit( } // Internal, version-checked, entry point. -WEBP_EXTERN(WebPAnimEncoder*) WebPAnimEncoderNewInternal( +WEBP_EXTERN WebPAnimEncoder* WebPAnimEncoderNewInternal( int, int, const WebPAnimEncoderOptions*, int); // Creates and initializes a WebPAnimEncoder object. @@ -490,7 +490,7 @@ static WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew( // Returns: // On error, returns false and frame->error_code is set appropriately. // Otherwise, returns true. -WEBP_EXTERN(int) WebPAnimEncoderAdd( +WEBP_EXTERN int WebPAnimEncoderAdd( WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms, const struct WebPConfig* config); @@ -503,8 +503,8 @@ WEBP_EXTERN(int) WebPAnimEncoderAdd( // webp_data - (out) generated WebP bitstream. // Returns: // True on success. -WEBP_EXTERN(int) WebPAnimEncoderAssemble(WebPAnimEncoder* enc, - WebPData* webp_data); +WEBP_EXTERN int WebPAnimEncoderAssemble(WebPAnimEncoder* enc, + WebPData* webp_data); // Get error string corresponding to the most recent call using 'enc'. The // returned string is owned by 'enc' and is valid only until the next call to @@ -514,12 +514,12 @@ WEBP_EXTERN(int) WebPAnimEncoderAssemble(WebPAnimEncoder* enc, // Returns: // NULL if 'enc' is NULL. Otherwise, returns the error string if the last call // to 'enc' had an error, or an empty string if the last call was a success. -WEBP_EXTERN(const char*) WebPAnimEncoderGetError(WebPAnimEncoder* enc); +WEBP_EXTERN const char* WebPAnimEncoderGetError(WebPAnimEncoder* enc); // Deletes the WebPAnimEncoder object. // Parameters: // enc - (in/out) object to be deleted -WEBP_EXTERN(void) WebPAnimEncoderDelete(WebPAnimEncoder* enc); +WEBP_EXTERN void WebPAnimEncoderDelete(WebPAnimEncoder* enc); //------------------------------------------------------------------------------ diff --git a/3rdparty/libwebp/webp/mux_types.h b/3rdparty/libwebp/src/webp/mux_types.h similarity index 100% rename from 3rdparty/libwebp/webp/mux_types.h rename to 3rdparty/libwebp/src/webp/mux_types.h diff --git a/3rdparty/libwebp/webp/types.h b/3rdparty/libwebp/src/webp/types.h similarity index 92% rename from 3rdparty/libwebp/webp/types.h rename to 3rdparty/libwebp/src/webp/types.h index 98fff35a11..989a763f0d 100644 --- a/3rdparty/libwebp/webp/types.h +++ b/3rdparty/libwebp/src/webp/types.h @@ -40,9 +40,9 @@ typedef long long int int64_t; // This explicitly marks library functions and allows for changing the // signature for e.g., Windows DLL builds. # if defined(__GNUC__) && __GNUC__ >= 4 -# define WEBP_EXTERN(type) extern __attribute__ ((visibility ("default"))) type +# define WEBP_EXTERN extern __attribute__ ((visibility ("default"))) # else -# define WEBP_EXTERN(type) extern type +# define WEBP_EXTERN extern # endif /* __GNUC__ >= 4 */ #endif /* WEBP_EXTERN */ diff --git a/3rdparty/libwebp/utils/Makefile.am b/3rdparty/libwebp/utils/Makefile.am deleted file mode 100644 index e346c0b430..0000000000 --- a/3rdparty/libwebp/utils/Makefile.am +++ /dev/null @@ -1,50 +0,0 @@ -noinst_LTLIBRARIES = libwebputils.la - -if BUILD_LIBWEBPDECODER - noinst_LTLIBRARIES += libwebputilsdecode.la -endif - -common_HEADERS = ../webp/types.h -commondir = $(includedir)/webp - -noinst_HEADERS = -noinst_HEADERS += ../dsp/dsp.h -noinst_HEADERS += ../webp/decode.h -noinst_HEADERS += ../webp/encode.h -noinst_HEADERS += ../webp/format_constants.h - -COMMON_SOURCES = -COMMON_SOURCES += bit_reader_utils.c -COMMON_SOURCES += bit_reader_utils.h -COMMON_SOURCES += bit_reader_inl_utils.h -COMMON_SOURCES += color_cache_utils.c -COMMON_SOURCES += color_cache_utils.h -COMMON_SOURCES += endian_inl_utils.h -COMMON_SOURCES += filters_utils.c -COMMON_SOURCES += filters_utils.h -COMMON_SOURCES += huffman_utils.c -COMMON_SOURCES += huffman_utils.h -COMMON_SOURCES += quant_levels_dec_utils.c -COMMON_SOURCES += quant_levels_dec_utils.h -COMMON_SOURCES += rescaler_utils.c -COMMON_SOURCES += rescaler_utils.h -COMMON_SOURCES += random_utils.c -COMMON_SOURCES += random_utils.h -COMMON_SOURCES += thread_utils.c -COMMON_SOURCES += thread_utils.h -COMMON_SOURCES += utils.c -COMMON_SOURCES += utils.h - -ENC_SOURCES = -ENC_SOURCES += bit_writer_utils.c -ENC_SOURCES += bit_writer_utils.h -ENC_SOURCES += huffman_encode_utils.c -ENC_SOURCES += huffman_encode_utils.h -ENC_SOURCES += quant_levels_utils.c -ENC_SOURCES += quant_levels_utils.h - -libwebputils_la_SOURCES = $(COMMON_SOURCES) $(ENC_SOURCES) - -if BUILD_LIBWEBPDECODER - libwebputilsdecode_la_SOURCES = $(COMMON_SOURCES) -endif diff --git a/cmake/OpenCVFindLibsGrfmt.cmake b/cmake/OpenCVFindLibsGrfmt.cmake index e96f29774e..0ae58c89f4 100644 --- a/cmake/OpenCVFindLibsGrfmt.cmake +++ b/cmake/OpenCVFindLibsGrfmt.cmake @@ -111,7 +111,7 @@ if(WITH_WEBP AND NOT WEBP_FOUND set(WEBP_LIBRARIES ${WEBP_LIBRARY}) add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libwebp") - set(WEBP_INCLUDE_DIR "${${WEBP_LIBRARY}_SOURCE_DIR}") + set(WEBP_INCLUDE_DIR "${${WEBP_LIBRARY}_SOURCE_DIR}/src") set(HAVE_WEBP 1) endif()