Merge remote-tracking branch 'upstream/3.4' into merge-3.4

pull/16899/head
Alexander Alekhin 5 years ago
commit ef395c3866
  1. 4
      3rdparty/libjpeg-turbo/CMakeLists.txt
  2. 62
      3rdparty/libjpeg-turbo/README.md
  3. 12
      3rdparty/libjpeg-turbo/src/jchuff.c
  4. 2
      3rdparty/libjpeg-turbo/src/jcmaster.c
  5. 4
      3rdparty/libjpeg-turbo/src/jcphuff.c
  6. 10
      3rdparty/libjpeg-turbo/src/jdhuff.c
  7. 2
      3rdparty/libjpeg-turbo/src/jdmerge.c
  8. 14
      3rdparty/libjpeg-turbo/src/jdsample.c
  9. 2
      3rdparty/libjpeg-turbo/src/jfdctint.c
  10. 2
      3rdparty/libjpeg-turbo/src/jidctint.c
  11. 2
      3rdparty/libjpeg-turbo/src/jidctred.c
  12. 14
      3rdparty/libtiff/CMakeLists.txt
  13. 4
      3rdparty/libtiff/snprintf.c
  14. 10
      3rdparty/libtiff/tif_aux.c
  15. 2
      3rdparty/libtiff/tif_config.h.cmake.in
  16. 50
      3rdparty/libtiff/tif_dir.c
  17. 200
      3rdparty/libtiff/tif_dirread.c
  18. 18
      3rdparty/libtiff/tif_dirwrite.c
  19. 11
      3rdparty/libtiff/tif_luv.c
  20. 2
      3rdparty/libtiff/tif_lzw.c
  21. 4
      3rdparty/libtiff/tif_pixarlog.c
  22. 8
      3rdparty/libtiff/tif_read.c
  23. 31
      3rdparty/libtiff/tif_webp.c
  24. 56
      3rdparty/libtiff/tif_zip.c
  25. 2
      3rdparty/libtiff/tiffiop.h
  26. 2
      3rdparty/libwebp/src/dec/frame_dec.c
  27. 11
      3rdparty/libwebp/src/dec/idec_dec.c
  28. 4
      3rdparty/libwebp/src/dec/vp8i_dec.h
  29. 10
      3rdparty/libwebp/src/dec/vp8l_dec.c
  30. 20
      3rdparty/libwebp/src/dec/vp8li_dec.h
  31. 4
      3rdparty/libwebp/src/demux/demux.c
  32. 9
      3rdparty/libwebp/src/dsp/dec_neon.c
  33. 4
      3rdparty/libwebp/src/dsp/dsp.h
  34. 11
      3rdparty/libwebp/src/dsp/lossless.c
  35. 2
      3rdparty/libwebp/src/dsp/lossless_common.h
  36. 3
      3rdparty/libwebp/src/dsp/lossless_enc_sse2.c
  37. 3
      3rdparty/libwebp/src/dsp/lossless_sse2.c
  38. 4
      3rdparty/libwebp/src/dsp/upsampling_msa.c
  39. 14
      3rdparty/libwebp/src/dsp/upsampling_neon.c
  40. 2
      3rdparty/libwebp/src/enc/histogram_enc.c
  41. 18
      3rdparty/libwebp/src/enc/picture_csp_enc.c
  42. 6
      3rdparty/libwebp/src/enc/vp8i_enc.h
  43. 4
      3rdparty/libwebp/src/mux/muxi.h
  44. 2
      3rdparty/libwebp/src/mux/muxread.c
  45. 2
      3rdparty/libwebp/src/utils/color_cache_utils.h
  46. 2
      3rdparty/libwebp/src/utils/thread_utils.c
  47. 9
      3rdparty/libwebp/src/utils/utils.c
  48. 5
      3rdparty/libwebp/src/webp/decode.h
  49. 9
      3rdparty/libwebp/src/webp/encode.h
  50. 12
      3rdparty/libwebp/src/webp/mux.h
  51. 10
      3rdparty/libwebp/src/webp/mux_types.h
  52. 18
      3rdparty/libwebp/src/webp/types.h
  53. 26
      3rdparty/tbb/CMakeLists.txt
  54. 1
      modules/calib3d/src/dls.cpp

@ -4,9 +4,9 @@ ocv_warnings_disable(CMAKE_C_FLAGS -Wunused-parameter -Wsign-compare -Wshorten-6
set(VERSION_MAJOR 2) set(VERSION_MAJOR 2)
set(VERSION_MINOR 0) set(VERSION_MINOR 0)
set(VERSION_REVISION 2) set(VERSION_REVISION 4)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION})
set(LIBJPEG_TURBO_VERSION_NUMBER 2000002) set(LIBJPEG_TURBO_VERSION_NUMBER 2000004)
string(TIMESTAMP BUILD "opencv-${OPENCV_VERSION}-libjpeg-turbo") string(TIMESTAMP BUILD "opencv-${OPENCV_VERSION}-libjpeg-turbo")
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")

@ -1,14 +1,14 @@
Background Background
========== ==========
libjpeg-turbo is a JPEG image codec that uses SIMD instructions (MMX, SSE2, libjpeg-turbo is a JPEG image codec that uses SIMD instructions to accelerate
AVX2, NEON, AltiVec) to accelerate baseline JPEG compression and decompression baseline JPEG compression and decompression on x86, x86-64, ARM, PowerPC, and
on x86, x86-64, ARM, and PowerPC systems, as well as progressive JPEG MIPS systems, as well as progressive JPEG compression on x86 and x86-64
compression on x86 and x86-64 systems. On such systems, libjpeg-turbo is systems. On such systems, libjpeg-turbo is generally 2-6x as fast as libjpeg,
generally 2-6x as fast as libjpeg, all else being equal. On other types of all else being equal. On other types of systems, libjpeg-turbo can still
systems, libjpeg-turbo can still outperform libjpeg by a significant amount, by outperform libjpeg by a significant amount, by virtue of its highly-optimized
virtue of its highly-optimized Huffman coding routines. In many cases, the Huffman coding routines. In many cases, the performance of libjpeg-turbo
performance of libjpeg-turbo rivals that of proprietary high-speed JPEG codecs. rivals that of proprietary high-speed JPEG codecs.
libjpeg-turbo implements both the traditional libjpeg API as well as the less libjpeg-turbo implements both the traditional libjpeg API as well as the less
powerful but more straightforward TurboJPEG API. libjpeg-turbo also features powerful but more straightforward TurboJPEG API. libjpeg-turbo also features
@ -135,25 +135,24 @@ without recompiling. libjpeg-turbo does not claim to support all of the
libjpeg v7+ features, nor to produce identical output to libjpeg v7+ in all libjpeg v7+ features, nor to produce identical output to libjpeg v7+ in all
cases (see below.) cases (see below.)
By passing an argument of `--with-jpeg7` or `--with-jpeg8` to `configure`, or By passing an argument of `-DWITH_JPEG7=1` or `-DWITH_JPEG8=1` to `cmake`, you
an argument of `-DWITH_JPEG7=1` or `-DWITH_JPEG8=1` to `cmake`, you can build a can build a version of libjpeg-turbo that emulates the libjpeg v7 or v8 ABI, so
version of libjpeg-turbo that emulates the libjpeg v7 or v8 ABI, so that that programs that are built against libjpeg v7 or v8 can be run with
programs that are built against libjpeg v7 or v8 can be run with libjpeg-turbo. libjpeg-turbo. The following section describes which libjpeg v7+ features are
The following section describes which libjpeg v7+ features are supported and supported and which aren't.
which aren't.
### Support for libjpeg v7 and v8 Features ### Support for libjpeg v7 and v8 Features
#### Fully supported #### Fully supported
- **libjpeg: IDCT scaling extensions in decompressor**<br> - **libjpeg API: IDCT scaling extensions in decompressor**<br>
libjpeg-turbo supports IDCT scaling with scaling factors of 1/8, 1/4, 3/8, libjpeg-turbo supports IDCT scaling with scaling factors of 1/8, 1/4, 3/8,
1/2, 5/8, 3/4, 7/8, 9/8, 5/4, 11/8, 3/2, 13/8, 7/4, 15/8, and 2/1 (only 1/4 1/2, 5/8, 3/4, 7/8, 9/8, 5/4, 11/8, 3/2, 13/8, 7/4, 15/8, and 2/1 (only 1/4
and 1/2 are SIMD-accelerated.) and 1/2 are SIMD-accelerated.)
- **libjpeg: Arithmetic coding** - **libjpeg API: Arithmetic coding**
- **libjpeg: In-memory source and destination managers**<br> - **libjpeg API: In-memory source and destination managers**<br>
See notes below. See notes below.
- **cjpeg: Separate quality settings for luminance and chrominance**<br> - **cjpeg: Separate quality settings for luminance and chrominance**<br>
@ -185,14 +184,14 @@ means of quality improvement. The reader is invited to peruse the research at
but it is the general belief of our project that these features have not but it is the general belief of our project that these features have not
demonstrated sufficient usefulness to justify inclusion in libjpeg-turbo. demonstrated sufficient usefulness to justify inclusion in libjpeg-turbo.
- **libjpeg: DCT scaling in compressor**<br> - **libjpeg API: DCT scaling in compressor**<br>
`cinfo.scale_num` and `cinfo.scale_denom` are silently ignored. `cinfo.scale_num` and `cinfo.scale_denom` are silently ignored.
There is no technical reason why DCT scaling could not be supported when There is no technical reason why DCT scaling could not be supported when
emulating the libjpeg v7+ API/ABI, but without the SmartScale extension (see emulating the libjpeg v7+ API/ABI, but without the SmartScale extension (see
below), only scaling factors of 1/2, 8/15, 4/7, 8/13, 2/3, 8/11, 4/5, and below), only scaling factors of 1/2, 8/15, 4/7, 8/13, 2/3, 8/11, 4/5, and
8/9 would be available, which is of limited usefulness. 8/9 would be available, which is of limited usefulness.
- **libjpeg: SmartScale**<br> - **libjpeg API: SmartScale**<br>
`cinfo.block_size` is silently ignored. `cinfo.block_size` is silently ignored.
SmartScale is an extension to the JPEG format that allows for DCT block SmartScale is an extension to the JPEG format that allows for DCT block
sizes other than 8x8. Providing support for this new format would be sizes other than 8x8. Providing support for this new format would be
@ -205,7 +204,7 @@ demonstrated sufficient usefulness to justify inclusion in libjpeg-turbo.
interest in providing this feature would be as a means of supporting interest in providing this feature would be as a means of supporting
additional DCT scaling factors. additional DCT scaling factors.
- **libjpeg: Fancy downsampling in compressor**<br> - **libjpeg API: Fancy downsampling in compressor**<br>
`cinfo.do_fancy_downsampling` is silently ignored. `cinfo.do_fancy_downsampling` is silently ignored.
This requires the DCT scaling feature, which is not supported. This requires the DCT scaling feature, which is not supported.
@ -247,15 +246,14 @@ don't, and it allows those functions to be provided in the "official"
libjpeg-turbo binaries. libjpeg-turbo binaries.
Those who are concerned about maintaining strict conformance with the libjpeg Those who are concerned about maintaining strict conformance with the libjpeg
v6b or v7 API can pass an argument of `--without-mem-srcdst` to `configure` or v6b or v7 API can pass an argument of `-DWITH_MEM_SRCDST=0` to `cmake` prior to
an argument of `-DWITH_MEM_SRCDST=0` to `cmake` prior to building building libjpeg-turbo. This will restore the pre-1.3 behavior, in which
libjpeg-turbo. This will restore the pre-1.3 behavior, in which
`jpeg_mem_src()` and `jpeg_mem_dest()` are only included when emulating the `jpeg_mem_src()` and `jpeg_mem_dest()` are only included when emulating the
libjpeg v8 API/ABI. libjpeg v8 API/ABI.
On Un*x systems, including the in-memory source/destination managers changes On Un*x systems, including the in-memory source/destination managers changes
the dynamic library version from 62.1.0 to 62.2.0 if using libjpeg v6b API/ABI the dynamic library version from 62.2.0 to 62.3.0 if using libjpeg v6b API/ABI
emulation and from 7.1.0 to 7.2.0 if using libjpeg v7 API/ABI emulation. emulation and from 7.2.0 to 7.3.0 if using libjpeg v7 API/ABI emulation.
Note that, on most Un*x systems, the dynamic linker will not look for a Note that, on most Un*x systems, the dynamic linker will not look for a
function in a library until that function is actually used. Thus, if a program function in a library until that function is actually used. Thus, if a program
@ -331,7 +329,7 @@ in a way that makes the rest of the libjpeg infrastructure happy, so it is
necessary to use the slow Huffman decoder when decompressing a JPEG image that necessary to use the slow Huffman decoder when decompressing a JPEG image that
has restart markers. This can cause the decompression performance to drop by has restart markers. This can cause the decompression performance to drop by
as much as 20%, but the performance will still be much greater than that of as much as 20%, but the performance will still be much greater than that of
libjpeg. Many consumer packages, such as PhotoShop, use restart markers when libjpeg. Many consumer packages, such as Photoshop, use restart markers when
generating JPEG images, so images generated by those programs will experience generating JPEG images, so images generated by those programs will experience
this issue. this issue.
@ -344,3 +342,15 @@ quality of 98-100. Thus, libjpeg-turbo must use the non-SIMD quantization
function in those cases. This causes performance to drop by as much as 40%. function in those cases. This causes performance to drop by as much as 40%.
It is therefore strongly advised that you use the slow integer forward DCT It is therefore strongly advised that you use the slow integer forward DCT
whenever encoding images with a JPEG quality of 98 or higher. whenever encoding images with a JPEG quality of 98 or higher.
Memory Debugger Pitfalls
========================
Valgrind and Memory Sanitizer (MSan) can generate false positives
(specifically, incorrect reports of uninitialized memory accesses) when used
with libjpeg-turbo's SIMD extensions. It is generally recommended that the
SIMD extensions be disabled, either by passing an argument of `-DWITH_SIMD=0`
to `cmake` when configuring the build or by setting the environment variable
`JSIMD_FORCENONE` to `1` at run time, when testing libjpeg-turbo with Valgrind,
MSan, or other memory debuggers.

@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software: * This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane. * Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2009-2011, 2014-2016, 2018, D. R. Commander. * Copyright (C) 2009-2011, 2014-2016, 2018-2019, D. R. Commander.
* Copyright (C) 2015, Matthieu Darbois. * Copyright (C) 2015, Matthieu Darbois.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
@ -43,8 +43,8 @@
*/ */
/* NOTE: Both GCC and Clang define __GNUC__ */ /* NOTE: Both GCC and Clang define __GNUC__ */
#if defined __GNUC__ && (defined __arm__ || defined __aarch64__) #if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))
#if !defined __thumb__ || defined __thumb2__ #if !defined(__thumb__) || defined(__thumb2__)
#define USE_CLZ_INTRINSIC #define USE_CLZ_INTRINSIC
#endif #endif
#endif #endif
@ -356,6 +356,8 @@ dump_buffer(working_state *state)
put_buffer = (put_buffer << size) | code; \ put_buffer = (put_buffer << size) | code; \
} }
#if SIZEOF_SIZE_T != 8 && !defined(_WIN64)
#define CHECKBUF15() { \ #define CHECKBUF15() { \
if (put_bits > 15) { \ if (put_bits > 15) { \
EMIT_BYTE() \ EMIT_BYTE() \
@ -363,6 +365,8 @@ dump_buffer(working_state *state)
} \ } \
} }
#endif
#define CHECKBUF31() { \ #define CHECKBUF31() { \
if (put_bits > 31) { \ if (put_bits > 31) { \
EMIT_BYTE() \ EMIT_BYTE() \
@ -428,7 +432,7 @@ dump_buffer(working_state *state)
* scanning order-- 1, 8, 16, etc.), then this will produce an encoded block * scanning order-- 1, 8, 16, etc.), then this will produce an encoded block
* larger than 200 bytes. * larger than 200 bytes.
*/ */
#define BUFSIZE (DCTSIZE2 * 4) #define BUFSIZE (DCTSIZE2 * 8)
#define LOAD_BUFFER() { \ #define LOAD_BUFFER() { \
if (state->free_in_buffer < BUFSIZE) { \ if (state->free_in_buffer < BUFSIZE) { \

@ -492,8 +492,8 @@ prepare_for_pass(j_compress_ptr cinfo)
*/ */
master->pass_type = output_pass; master->pass_type = output_pass;
master->pass_number++; master->pass_number++;
/*FALLTHROUGH*/
#endif #endif
/*FALLTHROUGH*/
case output_pass: case output_pass:
/* Do a data-output pass. */ /* Do a data-output pass. */
/* We need not repeat per-scan setup if prior optimization pass did it. */ /* We need not repeat per-scan setup if prior optimization pass did it. */

@ -52,8 +52,8 @@
*/ */
/* NOTE: Both GCC and Clang define __GNUC__ */ /* NOTE: Both GCC and Clang define __GNUC__ */
#if defined __GNUC__ && (defined __arm__ || defined __aarch64__) #if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))
#if !defined __thumb__ || defined __thumb2__ #if !defined(__thumb__) || defined(__thumb2__)
#define USE_CLZ_INTRINSIC #define USE_CLZ_INTRINSIC
#endif #endif
#endif #endif

@ -4,7 +4,7 @@
* This file was part of the Independent JPEG Group's software: * This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane. * Copyright (C) 1991-1997, Thomas G. Lane.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2009-2011, 2016, 2018, D. R. Commander. * Copyright (C) 2009-2011, 2016, 2018-2019, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
* *
@ -589,7 +589,11 @@ decode_mcu_slow(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (entropy->dc_needed[blkn]) { if (entropy->dc_needed[blkn]) {
/* Convert DC difference to actual value, update last_dc_val */ /* Convert DC difference to actual value, update last_dc_val */
int ci = cinfo->MCU_membership[blkn]; int ci = cinfo->MCU_membership[blkn];
s += state.last_dc_val[ci]; /* This is really just
* s += state.last_dc_val[ci];
* It is written this way in order to shut up UBSan.
*/
s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]);
state.last_dc_val[ci] = s; state.last_dc_val[ci] = s;
if (block) { if (block) {
/* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */ /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
@ -684,7 +688,7 @@ decode_mcu_fast(j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (entropy->dc_needed[blkn]) { if (entropy->dc_needed[blkn]) {
int ci = cinfo->MCU_membership[blkn]; int ci = cinfo->MCU_membership[blkn];
s += state.last_dc_val[ci]; s = (int)((unsigned int)s + (unsigned int)state.last_dc_val[ci]);
state.last_dc_val[ci] = s; state.last_dc_val[ci] = s;
if (block) if (block)
(*block)[0] = (JCOEF)s; (*block)[0] = (JCOEF)s;

@ -429,8 +429,6 @@ h2v2_merged_upsample(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
#define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l) #define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l)
#define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r) #define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r)
#define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3)
#define WRITE_TWO_PIXELS_LE(addr, pixels) { \ #define WRITE_TWO_PIXELS_LE(addr, pixels) { \
((INT16 *)(addr))[0] = (INT16)(pixels); \ ((INT16 *)(addr))[0] = (INT16)(pixels); \
((INT16 *)(addr))[1] = (INT16)((pixels) >> 16); \ ((INT16 *)(addr))[1] = (INT16)((pixels) >> 16); \

@ -8,6 +8,7 @@
* Copyright (C) 2010, 2015-2016, D. R. Commander. * Copyright (C) 2010, 2015-2016, D. R. Commander.
* Copyright (C) 2014, MIPS Technologies, Inc., California. * Copyright (C) 2014, MIPS Technologies, Inc., California.
* Copyright (C) 2015, Google, Inc. * Copyright (C) 2015, Google, Inc.
* Copyright (C) 2019, Arm Limited.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
* *
@ -315,9 +316,9 @@ h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
JSAMPARRAY output_data = *output_data_ptr; JSAMPARRAY output_data = *output_data_ptr;
JSAMPROW inptr0, inptr1, outptr; JSAMPROW inptr0, inptr1, outptr;
#if BITS_IN_JSAMPLE == 8 #if BITS_IN_JSAMPLE == 8
int thiscolsum; int thiscolsum, bias;
#else #else
JLONG thiscolsum; JLONG thiscolsum, bias;
#endif #endif
JDIMENSION colctr; JDIMENSION colctr;
int inrow, outrow, v; int inrow, outrow, v;
@ -327,15 +328,18 @@ h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr,
for (v = 0; v < 2; v++) { for (v = 0; v < 2; v++) {
/* inptr0 points to nearest input row, inptr1 points to next nearest */ /* inptr0 points to nearest input row, inptr1 points to next nearest */
inptr0 = input_data[inrow]; inptr0 = input_data[inrow];
if (v == 0) /* next nearest is row above */ if (v == 0) { /* next nearest is row above */
inptr1 = input_data[inrow - 1]; inptr1 = input_data[inrow - 1];
else /* next nearest is row below */ bias = 1;
} else { /* next nearest is row below */
inptr1 = input_data[inrow + 1]; inptr1 = input_data[inrow + 1];
bias = 2;
}
outptr = output_data[outrow++]; outptr = output_data[outrow++];
for (colctr = 0; colctr < compptr->downsampled_width; colctr++) { for (colctr = 0; colctr < compptr->downsampled_width; colctr++) {
thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
*outptr++ = (JSAMPLE)((thiscolsum + 1) >> 2); *outptr++ = (JSAMPLE)((thiscolsum + bias) >> 2);
} }
} }
inrow++; inrow++;

@ -1,7 +1,7 @@
/* /*
* jfdctint.c * jfdctint.c
* *
* This file was part of the Independent JPEG Group's software. * This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1996, Thomas G. Lane. * Copyright (C) 1991-1996, Thomas G. Lane.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2015, D. R. Commander. * Copyright (C) 2015, D. R. Commander.

@ -1,7 +1,7 @@
/* /*
* jidctint.c * jidctint.c
* *
* This file was part of the Independent JPEG Group's software. * This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1998, Thomas G. Lane. * Copyright (C) 1991-1998, Thomas G. Lane.
* Modification developed 2002-2009 by Guido Vollbeding. * Modification developed 2002-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:

@ -1,7 +1,7 @@
/* /*
* jidctred.c * jidctred.c
* *
* This file was part of the Independent JPEG Group's software. * This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1998, Thomas G. Lane. * Copyright (C) 1994-1998, Thomas G. Lane.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2015, D. R. Commander. * Copyright (C) 2015, D. R. Commander.

@ -126,30 +126,30 @@ endif()
if(SIZEOF_UNSIGNED_INT EQUAL SIZEOF_SIZE_T) if(SIZEOF_UNSIGNED_INT EQUAL SIZEOF_SIZE_T)
set(TIFF_SIZE_T "unsigned int") set(TIFF_SIZE_T "unsigned int")
set(TIFF_SIZE_FORMAT "%u") set(TIFF_SIZE_FORMAT "%u")
set(TIFF_SSIZE_T "signed int")
set(TIFF_SSIZE_FORMAT "%d")
elseif(SIZEOF_UNSIGNED_LONG EQUAL SIZEOF_SIZE_T) elseif(SIZEOF_UNSIGNED_LONG EQUAL SIZEOF_SIZE_T)
set(TIFF_SIZE_T "unsigned long") set(TIFF_SIZE_T "unsigned long")
set(TIFF_SIZE_FORMAT "%lu") set(TIFF_SIZE_FORMAT "%lu")
set(TIFF_SSIZE_T "signed long")
set(TIFF_SSIZE_FORMAT "%ld")
elseif(SIZEOF_UNSIGNED_LONG_LONG EQUAL SIZEOF_SIZE_T) elseif(SIZEOF_UNSIGNED_LONG_LONG EQUAL SIZEOF_SIZE_T)
set(TIFF_SIZE_T "unsigned long") set(TIFF_SIZE_T "unsigned long")
if(MINGW) if(MINGW)
set(TIFF_SIZE_FORMAT "%I64u") set(TIFF_SIZE_FORMAT "%I64u")
set(TIFF_SSIZE_FORMAT "%I64d")
else() else()
set(TIFF_SIZE_FORMAT "%llu") set(TIFF_SIZE_FORMAT "%llu")
set(TIFF_SSIZE_FORMAT "%lld")
endif() endif()
endif() endif()
if(SIZEOF_SIGNED_INT EQUAL SIZEOF_UNSIGNED_CHAR_P) 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) 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) elseif(SIZEOF_SIGNED_LONG_LONG EQUAL SIZEOF_UNSIGNED_CHAR_P)
set(TIFF_SSIZE_T "signed long long") set(TIFF_SSIZE_T "signed long long")
if(MINGW) if(MINGW)
set(TIFF_SSIZE_FORMAT "%I64d")
else() else()
set(TIFF_SSIZE_FORMAT "%lld")
endif() endif()
endif() endif()
@ -216,6 +216,8 @@ endif()
set(fillorder FILLORDER_MSB2LSB) set(fillorder FILLORDER_MSB2LSB)
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i.*86.*" OR if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i.*86.*" OR
CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64.*" OR CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64.*" OR
# AMD64 on Windows
CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "AMD64" OR
CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64.*") CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64.*")
set(fillorder FILLORDER_LSB2MSB) set(fillorder FILLORDER_LSB2MSB)
endif() endif()

@ -16,7 +16,11 @@ int _TIFF_vsnprintf_f(char* str, size_t size, const char* format, va_list ap)
int count = -1; int count = -1;
if (size != 0) if (size != 0)
#if _MSC_VER <= 1310
count = _vsnprintf(str, size, format, ap);
#else
count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
#endif
if (count == -1) if (count == -1)
count = _vscprintf(format, ap); count = _vscprintf(format, ap);

@ -30,6 +30,7 @@
#include "tiffiop.h" #include "tiffiop.h"
#include "tif_predict.h" #include "tif_predict.h"
#include <math.h> #include <math.h>
#include <float.h>
uint32 uint32
_TIFFMultiply32(TIFF* tif, uint32 first, uint32 second, const char* where) _TIFFMultiply32(TIFF* tif, uint32 first, uint32 second, const char* where)
@ -357,6 +358,15 @@ _TIFFUInt64ToDouble(uint64 ui64)
} }
} }
float _TIFFClampDoubleToFloat( double val )
{
if( val > FLT_MAX )
return FLT_MAX;
if( val < -FLT_MAX )
return -FLT_MAX;
return (float)val;
}
int _TIFFSeekOK(TIFF* tif, toff_t off) int _TIFFSeekOK(TIFF* tif, toff_t off)
{ {
/* Huge offsets, especially -1 / UINT64_MAX, can cause issues */ /* Huge offsets, especially -1 / UINT64_MAX, can cause issues */

@ -216,7 +216,7 @@
#endif #endif
/* Number of bits in a file offset, on hosts where this is settable. */ /* Number of bits in a file offset, on hosts where this is settable. */
//disabled for OpenCV CMakeLists.txt: #define _FILE_OFFSET_BITS @FILE_OFFSET_BITS@ #define _FILE_OFFSET_BITS @FILE_OFFSET_BITS@
/* Define to `__inline__' or `__inline' if that's what the C compiler /* 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. */ calls it, or to nothing if 'inline' is not supported under any name. */

@ -29,7 +29,6 @@
* (and also some miscellaneous stuff) * (and also some miscellaneous stuff)
*/ */
#include "tiffiop.h" #include "tiffiop.h"
#include <float.h>
/* /*
* These are used in the backwards compatibility code... * These are used in the backwards compatibility code...
@ -88,13 +87,15 @@ setDoubleArrayOneValue(double** vpp, double value, size_t nmemb)
* Install extra samples information. * Install extra samples information.
*/ */
static int static int
setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v) setExtraSamples(TIFF* tif, va_list ap, uint32* v)
{ {
/* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */ /* 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; uint16* va;
uint32 i; uint32 i;
TIFFDirectory* td = &tif->tif_dir;
static const char module[] = "setExtraSamples";
*v = (uint16) va_arg(ap, uint16_vap); *v = (uint16) va_arg(ap, uint16_vap);
if ((uint16) *v > td->td_samplesperpixel) if ((uint16) *v > td->td_samplesperpixel)
@ -116,6 +117,18 @@ setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v)
return 0; return 0;
} }
} }
if ( td->td_transferfunction[0] != NULL && (td->td_samplesperpixel - *v > 1) &&
!(td->td_samplesperpixel - td->td_extrasamples > 1))
{
TIFFWarningExt(tif->tif_clientdata,module,
"ExtraSamples tag value is changing, "
"but TransferFunction was read with a different value. Cancelling it");
TIFFClrFieldBit(tif,FIELD_TRANSFERFUNCTION);
_TIFFfree(td->td_transferfunction[0]);
td->td_transferfunction[0] = NULL;
}
td->td_extrasamples = (uint16) *v; td->td_extrasamples = (uint16) *v;
_TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples); _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples);
return 1; return 1;
@ -153,15 +166,6 @@ bad:
return (0); 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 static int
_TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
{ {
@ -285,6 +289,18 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
_TIFFfree(td->td_smaxsamplevalue); _TIFFfree(td->td_smaxsamplevalue);
td->td_smaxsamplevalue = NULL; td->td_smaxsamplevalue = NULL;
} }
/* Test if 3 transfer functions instead of just one are now needed
See http://bugzilla.maptools.org/show_bug.cgi?id=2820 */
if( td->td_transferfunction[0] != NULL && (v - td->td_extrasamples > 1) &&
!(td->td_samplesperpixel - td->td_extrasamples > 1))
{
TIFFWarningExt(tif->tif_clientdata,module,
"SamplesPerPixel tag value is changing, "
"but TransferFunction was read with a different value. Cancelling it");
TIFFClrFieldBit(tif,FIELD_TRANSFERFUNCTION);
_TIFFfree(td->td_transferfunction[0]);
td->td_transferfunction[0] = NULL;
}
} }
td->td_samplesperpixel = (uint16) v; td->td_samplesperpixel = (uint16) v;
break; break;
@ -320,13 +336,13 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
dblval = va_arg(ap, double); dblval = va_arg(ap, double);
if( dblval < 0 ) if( dblval < 0 )
goto badvaluedouble; goto badvaluedouble;
td->td_xresolution = TIFFClampDoubleToFloat( dblval ); td->td_xresolution = _TIFFClampDoubleToFloat( dblval );
break; break;
case TIFFTAG_YRESOLUTION: case TIFFTAG_YRESOLUTION:
dblval = va_arg(ap, double); dblval = va_arg(ap, double);
if( dblval < 0 ) if( dblval < 0 )
goto badvaluedouble; goto badvaluedouble;
td->td_yresolution = TIFFClampDoubleToFloat( dblval ); td->td_yresolution = _TIFFClampDoubleToFloat( dblval );
break; break;
case TIFFTAG_PLANARCONFIG: case TIFFTAG_PLANARCONFIG:
v = (uint16) va_arg(ap, uint16_vap); v = (uint16) va_arg(ap, uint16_vap);
@ -335,10 +351,10 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
td->td_planarconfig = (uint16) v; td->td_planarconfig = (uint16) v;
break; break;
case TIFFTAG_XPOSITION: case TIFFTAG_XPOSITION:
td->td_xposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); td->td_xposition = _TIFFClampDoubleToFloat( va_arg(ap, double) );
break; break;
case TIFFTAG_YPOSITION: case TIFFTAG_YPOSITION:
td->td_yposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); td->td_yposition = _TIFFClampDoubleToFloat( va_arg(ap, double) );
break; break;
case TIFFTAG_RESOLUTIONUNIT: case TIFFTAG_RESOLUTIONUNIT:
v = (uint16) va_arg(ap, uint16_vap); v = (uint16) va_arg(ap, uint16_vap);
@ -361,7 +377,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
_TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32); _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32);
break; break;
case TIFFTAG_EXTRASAMPLES: case TIFFTAG_EXTRASAMPLES:
if (!setExtraSamples(td, ap, &v)) if (!setExtraSamples(tif, ap, &v))
goto badvalue; goto badvalue;
break; break;
case TIFFTAG_MATTEING: case TIFFTAG_MATTEING:
@ -684,7 +700,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
case TIFF_SRATIONAL: case TIFF_SRATIONAL:
case TIFF_FLOAT: case TIFF_FLOAT:
{ {
float v2 = TIFFClampDoubleToFloat(va_arg(ap, double)); float v2 = _TIFFClampDoubleToFloat(va_arg(ap, double));
_TIFFmemcpy(val, &v2, tv_size); _TIFFmemcpy(val, &v2, tv_size);
} }
break; break;

@ -164,6 +164,7 @@ static int TIFFFetchNormalTag(TIFF*, TIFFDirEntry*, int recover);
static int TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp); static int TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp);
static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*); static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*);
static void ChopUpSingleUncompressedStrip(TIFF*); static void ChopUpSingleUncompressedStrip(TIFF*);
static void TryChopUpUncompressedBigTiff(TIFF*);
static uint64 TIFFReadUInt64(const uint8 *value); static uint64 TIFFReadUInt64(const uint8 *value);
static int _TIFFGetMaxColorChannels(uint16 photometric); static int _TIFFGetMaxColorChannels(uint16 photometric);
@ -4246,6 +4247,19 @@ TIFFReadDirectory(TIFF* tif)
ChopUpSingleUncompressedStrip(tif); ChopUpSingleUncompressedStrip(tif);
} }
/* There are also uncompressed stripped files with strips larger than */
/* 2 GB, which make them unfriendly with a lot of code. If possible, */
/* try to expose smaller "virtual" strips. */
if( tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG &&
tif->tif_dir.td_compression == COMPRESSION_NONE &&
(tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP &&
TIFFStripSize64(tif) > 0x7FFFFFFFUL )
{
if ( !_TIFFFillStriles(tif) || !tif->tif_dir.td_stripbytecount )
return 0;
TryChopUpUncompressedBigTiff(tif);
}
/* /*
* Clear the dirty directory flag. * Clear the dirty directory flag.
*/ */
@ -5699,6 +5713,63 @@ TIFFFetchSubjectDistance(TIFF* tif, TIFFDirEntry* dir)
} }
} }
static void allocChoppedUpStripArrays(TIFF* tif, uint32 nstrips,
uint64 stripbytes, uint32 rowsperstrip)
{
TIFFDirectory *td = &tif->tif_dir;
uint64 bytecount;
uint64 offset;
uint32 i;
uint64 *newcounts;
uint64 *newoffsets;
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.
*/
offset = td->td_stripoffset[0];
bytecount = td->td_stripoffset[td->td_nstrips-1] +
td->td_stripbytecount[td->td_nstrips-1] - offset;
for (i = 0; i < nstrips; i++)
{
if (stripbytes > bytecount)
stripbytes = bytecount;
newcounts[i] = stripbytes;
newoffsets[i] = 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;
}
/* /*
* Replace a single strip (tile) of uncompressed data by multiple strips * Replace a single strip (tile) of uncompressed data by multiple strips
* (tiles), each approximately STRIP_SIZE_DEFAULT bytes. This is useful for * (tiles), each approximately STRIP_SIZE_DEFAULT bytes. This is useful for
@ -5714,11 +5785,8 @@ ChopUpSingleUncompressedStrip(TIFF* tif)
uint32 rowblock; uint32 rowblock;
uint64 rowblockbytes; uint64 rowblockbytes;
uint64 stripbytes; uint64 stripbytes;
uint32 strip;
uint32 nstrips; uint32 nstrips;
uint32 rowsperstrip; uint32 rowsperstrip;
uint64* newcounts;
uint64* newoffsets;
bytecount = td->td_stripbytecount[0]; bytecount = td->td_stripbytecount[0];
/* On a newly created file, just re-opened to be filled, we */ /* On a newly created file, just re-opened to be filled, we */
@ -5769,46 +5837,106 @@ ChopUpSingleUncompressedStrip(TIFF* tif)
return; return;
} }
newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), allocChoppedUpStripArrays(tif, nstrips, stripbytes, rowsperstrip);
"for chopped \"StripByteCounts\" array"); }
newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64),
"for chopped \"StripOffsets\" array");
if (newcounts == NULL || newoffsets == NULL) { /*
/* * Replace a file with contiguous strips > 2 GB of uncompressed data by
* Unable to allocate new strip information, give up and use * multiple smaller strips. This is useful for
* the original one strip information. * dealing with large images or for dealing with machines with a limited
* amount memory.
*/ */
if (newcounts != NULL) static void TryChopUpUncompressedBigTiff( TIFF* tif )
_TIFFfree(newcounts); {
if (newoffsets != NULL) TIFFDirectory *td = &tif->tif_dir;
_TIFFfree(newoffsets); uint32 rowblock;
uint64 rowblockbytes;
uint32 i;
uint64 stripsize;
uint32 rowblocksperstrip;
uint32 rowsperstrip;
uint64 stripbytes;
uint32 nstrips;
stripsize = TIFFStripSize64(tif);
assert( tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG );
assert( tif->tif_dir.td_compression == COMPRESSION_NONE );
assert( (tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP );
assert( stripsize > 0x7FFFFFFFUL );
/* 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( td->td_stripbytecount[0] == 0 && tif->tif_mode != O_RDONLY )
return;
if ((td->td_photometric == PHOTOMETRIC_YCBCR)&&
(!isUpSampled(tif)))
rowblock = td->td_ycbcrsubsampling[1];
else
rowblock = 1;
rowblockbytes = TIFFVStripSize64(tif, rowblock);
if( rowblockbytes == 0 || rowblockbytes > 0x7FFFFFFFUL )
{
/* In case of file with gigantic width */
return; return;
} }
/*
* Fill the strip information arrays with new bytecounts and offsets /* Check that the strips are contiguous and of the expected size */
* that reflect the broken-up format. for( i = 0; i < td->td_nstrips; i++ )
*/ {
for (strip = 0; strip < nstrips; strip++) { if( i == td->td_nstrips - 1 )
if (stripbytes > bytecount) {
stripbytes = bytecount; if( td->td_stripbytecount[i] < TIFFVStripSize64(
newcounts[strip] = stripbytes; tif, td->td_imagelength - i * td->td_rowsperstrip ) )
newoffsets[strip] = stripbytes ? offset : 0; {
offset += stripbytes; return;
bytecount -= stripbytes; }
}
else
{
if( td->td_stripbytecount[i] != stripsize )
{
return;
}
if( i > 0 && td->td_stripoffset[i] !=
td->td_stripoffset[i-1] + td->td_stripbytecount[i - 1] )
{
return;
}
}
} }
/*
* 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); /* Aim for 512 MB strips (that will still be manageable by 32 bit builds */
_TIFFfree(td->td_stripoffset); rowblocksperstrip = (uint32) (512 * 1024 * 1024 / rowblockbytes);
td->td_stripbytecount = newcounts; if( rowblocksperstrip == 0 )
td->td_stripoffset = newoffsets; rowblocksperstrip = 1;
td->td_stripbytecountsorted = 1; rowsperstrip = rowblocksperstrip * rowblock;
stripbytes = rowblocksperstrip * rowblockbytes;
assert( stripbytes <= 0x7FFFFFFFUL );
nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip);
if( nstrips == 0 )
return;
/* If we are going to allocate a lot of memory, make sure that the */
/* file is as big as needed */
if( tif->tif_mode == O_RDONLY &&
nstrips > 1000000 &&
(td->td_stripoffset[td->td_nstrips-1] > TIFFGetFileSize(tif) ||
td->td_stripoffset[td->td_nstrips-1] +
td->td_stripbytecount[td->td_nstrips-1] > TIFFGetFileSize(tif)) )
{
return;
}
allocChoppedUpStripArrays(tif, nstrips, stripbytes, rowsperstrip);
} }
int _TIFFFillStriles( TIFF *tif ) int _TIFFFillStriles( TIFF *tif )
{ {
return _TIFFFillStrilesInternal( tif, 1 ); return _TIFFFillStrilesInternal( tif, 1 );

@ -28,7 +28,6 @@
* Directory Write Support Routines. * Directory Write Support Routines.
*/ */
#include "tiffiop.h" #include "tiffiop.h"
#include <float.h>
#ifdef HAVE_IEEEFP #ifdef HAVE_IEEEFP
#define TIFFCvtNativeToIEEEFloat(tif, n, fp) #define TIFFCvtNativeToIEEEFloat(tif, n, fp)
@ -946,15 +945,6 @@ bad:
return(0); 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 ) static int8 TIFFClampDoubleToInt8( double val )
{ {
if( val > 127 ) if( val > 127 )
@ -1029,7 +1019,7 @@ TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* di
if (tif->tif_dir.td_bitspersample<=32) if (tif->tif_dir.td_bitspersample<=32)
{ {
for (i = 0; i < count; ++i) for (i = 0; i < count; ++i)
((float*)conv)[i] = TIFFClampDoubleToFloat(value[i]); ((float*)conv)[i] = _TIFFClampDoubleToFloat(value[i]);
ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv); ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv);
} }
else else
@ -1893,12 +1883,14 @@ TIFFWriteDirectoryTagTransferfunction(TIFF* tif, uint32* ndir, TIFFDirEntry* dir
n=3; n=3;
if (n==3) if (n==3)
{ {
if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16))) if (tif->tif_dir.td_transferfunction[2] == NULL ||
!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16)))
n=2; n=2;
} }
if (n==2) if (n==2)
{ {
if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16))) if (tif->tif_dir.td_transferfunction[1] == NULL ||
!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16)))
n=1; n=1;
} }
if (n==0) if (n==0)

@ -742,9 +742,14 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
#undef exp2 /* Conflict with C'99 function */ #undef exp2 /* Conflict with C'99 function */
#define exp2(x) exp(M_LN2*(x)) #define exp2(x) exp(M_LN2*(x))
#define itrunc(x,m) ((m)==SGILOGENCODE_NODITHER ? \ static int itrunc(double x, int m)
(int)(x) : \ {
(int)((x) + rand()*(1./RAND_MAX) - .5)) if( m == SGILOGENCODE_NODITHER )
return (int)x;
/* Silence CoverityScan warning about bad crypto function */
/* coverity[dont_call] */
return (int)(x + rand()*(1./RAND_MAX) - .5);
}
#if !LOGLUV_PUBLIC #if !LOGLUV_PUBLIC
static static

@ -247,6 +247,8 @@ LZWSetupDecode(TIFF* tif)
/* /*
* Zero-out the unused entries * Zero-out the unused entries
*/ */
/* Silence false positive */
/* coverity[overrun-buffer-arg] */
_TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0, _TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0,
(CODE_FIRST - CODE_CLEAR) * sizeof (code_t)); (CODE_FIRST - CODE_CLEAR) * sizeof (code_t));
} }

@ -640,6 +640,7 @@ PixarLogGuessDataFmt(TIFFDirectory *td)
static tmsize_t static tmsize_t
multiply_ms(tmsize_t m1, tmsize_t m2) multiply_ms(tmsize_t m1, tmsize_t m2)
{ {
assert(m1 >= 0 && m2 >= 0);
if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 ) if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 )
return 0; return 0;
return m1 * m2; return m1 * m2;
@ -648,6 +649,7 @@ multiply_ms(tmsize_t m1, tmsize_t m2)
static tmsize_t static tmsize_t
add_ms(tmsize_t m1, tmsize_t m2) add_ms(tmsize_t m1, tmsize_t m2)
{ {
assert(m1 >= 0 && m2 >= 0);
/* if either input is zero, assume overflow already occurred */ /* if either input is zero, assume overflow already occurred */
if (m1 == 0 || m2 == 0) if (m1 == 0 || m2 == 0)
return 0; return 0;
@ -817,9 +819,7 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Decoding error at scanline %lu, %s", "Decoding error at scanline %lu, %s",
(unsigned long) tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)"); (unsigned long) tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
if (inflateSync(&sp->stream) != Z_OK)
return (0); return (0);
continue;
} }
if (state != Z_OK) { if (state != Z_OK) {
TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s",

@ -103,6 +103,11 @@ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size,
} }
tif->tif_rawdata = new_rawdata; tif->tif_rawdata = new_rawdata;
} }
if( tif->tif_rawdata == NULL )
{
/* should not happen in practice but helps CoverityScan */
return 0;
}
bytes_read = TIFFReadFile(tif, bytes_read = TIFFReadFile(tif,
tif->tif_rawdata + rawdata_offset + already_read, to_read); tif->tif_rawdata + rawdata_offset + already_read, to_read);
@ -1367,7 +1372,8 @@ TIFFFillTile(TIFF* tif, uint32 tile)
tif->tif_rawdataoff = 0; tif->tif_rawdataoff = 0;
tif->tif_rawdataloaded = bytecountm; tif->tif_rawdataloaded = bytecountm;
if (!isFillOrder(tif, td->td_fillorder) && if (tif->tif_rawdata != NULL &&
!isFillOrder(tif, td->td_fillorder) &&
(tif->tif_flags & TIFF_NOBITREV) == 0) (tif->tif_flags & TIFF_NOBITREV) == 0)
TIFFReverseBits(tif->tif_rawdata, TIFFReverseBits(tif->tif_rawdata,
tif->tif_rawdataloaded); tif->tif_rawdataloaded);

@ -349,6 +349,12 @@ TWebPSetupEncode(TIFF* tif)
sp->state |= LSTATE_INIT_ENCODE; sp->state |= LSTATE_INIT_ENCODE;
if (!WebPPictureInit(&sp->sPicture)) {
TIFFErrorExt(tif->tif_clientdata, module,
"Error initializing WebP picture.");
return 0;
}
if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT, if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT,
sp->quality_level, sp->quality_level,
WEBP_ENCODER_ABI_VERSION)) { WEBP_ENCODER_ABI_VERSION)) {
@ -357,9 +363,13 @@ TWebPSetupEncode(TIFF* tif)
return 0; return 0;
} }
#if WEBP_ENCODER_ABI_VERSION >= 0x0100 // WebPConfigInitInternal above sets lossless to false
#if WEBP_ENCODER_ABI_VERSION >= 0x0100
sp->sEncoderConfig.lossless = sp->lossless; sp->sEncoderConfig.lossless = sp->lossless;
#endif if (sp->lossless) {
sp->sPicture.use_argb = 1;
}
#endif
if (!WebPValidateConfig(&sp->sEncoderConfig)) { if (!WebPValidateConfig(&sp->sEncoderConfig)) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
@ -367,12 +377,6 @@ TWebPSetupEncode(TIFF* tif)
return 0; return 0;
} }
if (!WebPPictureInit(&sp->sPicture)) {
TIFFErrorExt(tif->tif_clientdata, module,
"Error initializing WebP picture.");
return 0;
}
return 1; return 1;
} }
@ -415,6 +419,12 @@ TWebPPreEncode(TIFF* tif, uint16 s)
/* set up buffer for raw data */ /* set up buffer for raw data */
/* given above check and that nSamples <= 4, buffer_size is <= 1 GB */ /* given above check and that nSamples <= 4, buffer_size is <= 1 GB */
sp->buffer_size = segment_width * segment_height * sp->nSamples; sp->buffer_size = segment_width * segment_height * sp->nSamples;
if (sp->pBuffer != NULL) {
_TIFFfree(sp->pBuffer);
sp->pBuffer = NULL;
}
sp->pBuffer = _TIFFmalloc(sp->buffer_size); sp->pBuffer = _TIFFmalloc(sp->buffer_size);
if( !sp->pBuffer) { if( !sp->pBuffer) {
TIFFErrorExt(tif->tif_clientdata, module, "Cannot allocate buffer"); TIFFErrorExt(tif->tif_clientdata, module, "Cannot allocate buffer");
@ -544,10 +554,8 @@ TWebPCleanup(TIFF* tif)
sp->pBuffer = NULL; sp->pBuffer = NULL;
} }
if (tif->tif_data) {
_TIFFfree(tif->tif_data); _TIFFfree(tif->tif_data);
tif->tif_data = NULL; tif->tif_data = NULL;
}
_TIFFSetDefaultCompressionState(tif); _TIFFSetDefaultCompressionState(tif);
} }
@ -570,6 +578,9 @@ TWebPVSetField(TIFF* tif, uint32 tag, va_list ap)
case TIFFTAG_WEBP_LOSSLESS: case TIFFTAG_WEBP_LOSSLESS:
#if WEBP_ENCODER_ABI_VERSION >= 0x0100 #if WEBP_ENCODER_ABI_VERSION >= 0x0100
sp->lossless = va_arg(ap, int); sp->lossless = va_arg(ap, int);
if (sp->lossless){
sp->quality_level = 100.0f;
}
return 1; return 1;
#else #else
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,

@ -124,7 +124,6 @@ ZIPSetupDecode(TIFF* tif)
static int static int
ZIPPreDecode(TIFF* tif, uint16 s) ZIPPreDecode(TIFF* tif, uint16 s)
{ {
static const char module[] = "ZIPPreDecode";
ZIPState* sp = DecoderState(tif); ZIPState* sp = DecoderState(tif);
(void) s; (void) s;
@ -138,12 +137,7 @@ ZIPPreDecode(TIFF* tif, uint16 s)
we need to simplify this code to reflect a ZLib that is likely updated 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 to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ appropriately even before we simplify it */
sp->stream.avail_in = (uInt) tif->tif_rawcc; sp->stream.avail_in = (uint64)tif->tif_rawcc < 0xFFFFFFFFU ? (uInt) tif->tif_rawcc : 0xFFFFFFFFU;
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); return (inflateReset(&sp->stream) == Z_OK);
} }
@ -158,46 +152,43 @@ ZIPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
assert(sp->state == ZSTATE_INIT_DECODE); assert(sp->state == ZSTATE_INIT_DECODE);
sp->stream.next_in = tif->tif_rawcp; sp->stream.next_in = tif->tif_rawcp;
sp->stream.avail_in = (uInt) tif->tif_rawcc;
sp->stream.next_out = op; sp->stream.next_out = op;
assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, 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 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 to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ 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 { do {
int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); int state;
uInt avail_in_before = (uint64)tif->tif_rawcc <= 0xFFFFFFFFU ? (uInt)tif->tif_rawcc : 0xFFFFFFFFU;
uInt avail_out_before = (uint64)occ < 0xFFFFFFFFU ? (uInt) occ : 0xFFFFFFFFU;
sp->stream.avail_in = avail_in_before;
sp->stream.avail_out = avail_out_before;
state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
tif->tif_rawcc -= (avail_in_before - sp->stream.avail_in);
occ -= (avail_out_before - sp->stream.avail_out);
if (state == Z_STREAM_END) if (state == Z_STREAM_END)
break; break;
if (state == Z_DATA_ERROR) { if (state == Z_DATA_ERROR) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Decoding error at scanline %lu, %s", "Decoding error at scanline %lu, %s",
(unsigned long) tif->tif_row, SAFE_MSG(sp)); (unsigned long) tif->tif_row, SAFE_MSG(sp));
if (inflateSync(&sp->stream) != Z_OK)
return (0); return (0);
continue;
} }
if (state != Z_OK) { if (state != Z_OK) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"ZLib error: %s", SAFE_MSG(sp)); "ZLib error: %s", SAFE_MSG(sp));
return (0); return (0);
} }
} while (sp->stream.avail_out > 0); } while (occ > 0);
if (sp->stream.avail_out != 0) { if (occ != 0) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Not enough data at scanline %lu (short " TIFF_UINT64_FORMAT " bytes)", "Not enough data at scanline %lu (short " TIFF_UINT64_FORMAT " bytes)",
(unsigned long) tif->tif_row, (TIFF_UINT64_T) sp->stream.avail_out); (unsigned long) tif->tif_row, (TIFF_UINT64_T) occ);
return (0); return (0);
} }
tif->tif_rawcp = sp->stream.next_in; tif->tif_rawcp = sp->stream.next_in;
tif->tif_rawcc = sp->stream.avail_in;
return (1); return (1);
} }
@ -229,7 +220,6 @@ ZIPSetupEncode(TIFF* tif)
static int static int
ZIPPreEncode(TIFF* tif, uint16 s) ZIPPreEncode(TIFF* tif, uint16 s)
{ {
static const char module[] = "ZIPPreEncode";
ZIPState *sp = EncoderState(tif); ZIPState *sp = EncoderState(tif);
(void) s; (void) s;
@ -242,12 +232,7 @@ ZIPPreEncode(TIFF* tif, uint16 s)
we need to simplify this code to reflect a ZLib that is likely updated 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 to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ appropriately even before we simplify it */
sp->stream.avail_out = (uInt)tif->tif_rawdatasize; sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU;
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); return (deflateReset(&sp->stream) == Z_OK);
} }
@ -269,13 +254,9 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
we need to simplify this code to reflect a ZLib that is likely updated 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 to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ 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 { do {
uInt avail_in_before = (uint64)cc <= 0xFFFFFFFFU ? (uInt)cc : 0xFFFFFFFFU;
sp->stream.avail_in = avail_in_before;
if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Encoder error: %s", "Encoder error: %s",
@ -286,9 +267,10 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
tif->tif_rawcc = tif->tif_rawdatasize; tif->tif_rawcc = tif->tif_rawdatasize;
TIFFFlushData1(tif); TIFFFlushData1(tif);
sp->stream.next_out = tif->tif_rawdata; 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 */ sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU;
} }
} while (sp->stream.avail_in > 0); cc -= (avail_in_before - sp->stream.avail_in);
} while (cc > 0);
return (1); return (1);
} }
@ -314,7 +296,7 @@ ZIPPostEncode(TIFF* tif)
tif->tif_rawcc = tif->tif_rawdatasize - sp->stream.avail_out; tif->tif_rawcc = tif->tif_rawdatasize - sp->stream.avail_out;
TIFFFlushData1(tif); TIFFFlushData1(tif);
sp->stream.next_out = tif->tif_rawdata; 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 */ sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU;
} }
break; break;
default: default:

@ -374,6 +374,8 @@ extern void* _TIFFCheckRealloc(TIFF*, void*, tmsize_t, tmsize_t, const char*);
extern double _TIFFUInt64ToDouble(uint64); extern double _TIFFUInt64ToDouble(uint64);
extern float _TIFFUInt64ToFloat(uint64); extern float _TIFFUInt64ToFloat(uint64);
extern float _TIFFClampDoubleToFloat(double);
extern tmsize_t extern tmsize_t
_TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, _TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip,
void **buf, tmsize_t bufsizetoalloc, void **buf, tmsize_t bufsizetoalloc,

@ -732,7 +732,7 @@ static int AllocateMemory(VP8Decoder* const dec) {
mem += f_info_size; mem += f_info_size;
dec->thread_ctx_.id_ = 0; dec->thread_ctx_.id_ = 0;
dec->thread_ctx_.f_info_ = dec->f_info_; dec->thread_ctx_.f_info_ = dec->f_info_;
if (dec->mt_method_ > 0) { if (dec->filter_type_ > 0 && dec->mt_method_ > 0) {
// secondary cache line. The deblocking process need to make use of the // secondary cache line. The deblocking process need to make use of the
// filtering strength from previous macroblock row, while the new ones // filtering strength from previous macroblock row, while the new ones
// are being decoded in parallel. We'll just swap the pointers. // are being decoded in parallel. We'll just swap the pointers.

@ -166,9 +166,11 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
VP8Decoder* const dec = (VP8Decoder*)idec->dec_; VP8Decoder* const dec = (VP8Decoder*)idec->dec_;
MemBuffer* const mem = &idec->mem_; MemBuffer* const mem = &idec->mem_;
const int need_compressed_alpha = NeedCompressedAlpha(idec); const int need_compressed_alpha = NeedCompressedAlpha(idec);
const uint8_t* const old_start = mem->buf_ + mem->start_; const uint8_t* const old_start =
(mem->buf_ == NULL) ? NULL : mem->buf_ + mem->start_;
const uint8_t* const old_base = const uint8_t* const old_base =
need_compressed_alpha ? dec->alpha_data_ : old_start; need_compressed_alpha ? dec->alpha_data_ : old_start;
assert(mem->buf_ != NULL || mem->start_ == 0);
assert(mem->mode_ == MEM_MODE_APPEND); assert(mem->mode_ == MEM_MODE_APPEND);
if (data_size > MAX_CHUNK_PAYLOAD) { if (data_size > MAX_CHUNK_PAYLOAD) {
// security safeguard: trying to allocate more than what the format // security safeguard: trying to allocate more than what the format
@ -184,7 +186,7 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
uint8_t* const new_buf = uint8_t* const new_buf =
(uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf)); (uint8_t*)WebPSafeMalloc(extra_size, sizeof(*new_buf));
if (new_buf == NULL) return 0; if (new_buf == NULL) return 0;
memcpy(new_buf, old_base, current_size); if (old_base != NULL) memcpy(new_buf, old_base, current_size);
WebPSafeFree(mem->buf_); WebPSafeFree(mem->buf_);
mem->buf_ = new_buf; mem->buf_ = new_buf;
mem->buf_size_ = (size_t)extra_size; mem->buf_size_ = (size_t)extra_size;
@ -192,6 +194,7 @@ static int AppendToMemBuffer(WebPIDecoder* const idec,
mem->end_ = current_size; mem->end_ = current_size;
} }
assert(mem->buf_ != NULL);
memcpy(mem->buf_ + mem->end_, data, data_size); memcpy(mem->buf_ + mem->end_, data, data_size);
mem->end_ += data_size; mem->end_ += data_size;
assert(mem->end_ <= mem->buf_size_); assert(mem->end_ <= mem->buf_size_);
@ -204,7 +207,9 @@ static int RemapMemBuffer(WebPIDecoder* const idec,
const uint8_t* const data, size_t data_size) { const uint8_t* const data, size_t data_size) {
MemBuffer* const mem = &idec->mem_; MemBuffer* const mem = &idec->mem_;
const uint8_t* const old_buf = mem->buf_; const uint8_t* const old_buf = mem->buf_;
const uint8_t* const old_start = old_buf + mem->start_; const uint8_t* const old_start =
(old_buf == NULL) ? NULL : old_buf + mem->start_;
assert(old_buf != NULL || mem->start_ == 0);
assert(mem->mode_ == MEM_MODE_MAP); assert(mem->mode_ == MEM_MODE_MAP);
if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer! if (data_size < mem->buf_size_) return 0; // can't remap to a shorter buffer!

@ -31,8 +31,8 @@ extern "C" {
// version numbers // version numbers
#define DEC_MAJ_VERSION 1 #define DEC_MAJ_VERSION 1
#define DEC_MIN_VERSION 0 #define DEC_MIN_VERSION 1
#define DEC_REV_VERSION 3 #define DEC_REV_VERSION 0
// YUV-cache parameters. Cache is 32-bytes wide (= one cacheline). // YUV-cache parameters. Cache is 32-bytes wide (= one cacheline).
// Constraints are: We need to store one 16x16 block of luma samples (y), // Constraints are: We need to store one 16x16 block of luma samples (y),

@ -754,11 +754,11 @@ static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row); typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
static void ApplyInverseTransforms(VP8LDecoder* const dec, int num_rows, static void ApplyInverseTransforms(VP8LDecoder* const dec,
int start_row, int num_rows,
const uint32_t* const rows) { const uint32_t* const rows) {
int n = dec->next_transform_; int n = dec->next_transform_;
const int cache_pixs = dec->width_ * num_rows; const int cache_pixs = dec->width_ * num_rows;
const int start_row = dec->last_row_;
const int end_row = start_row + num_rows; const int end_row = start_row + num_rows;
const uint32_t* rows_in = rows; const uint32_t* rows_in = rows;
uint32_t* const rows_out = dec->argb_cache_; uint32_t* const rows_out = dec->argb_cache_;
@ -789,8 +789,7 @@ static void ProcessRows(VP8LDecoder* const dec, int row) {
VP8Io* const io = dec->io_; VP8Io* const io = dec->io_;
uint8_t* rows_data = (uint8_t*)dec->argb_cache_; uint8_t* rows_data = (uint8_t*)dec->argb_cache_;
const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA const int in_stride = io->width * sizeof(uint32_t); // in unit of RGBA
ApplyInverseTransforms(dec, dec->last_row_, num_rows, rows);
ApplyInverseTransforms(dec, num_rows, rows);
if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) { if (!SetCropWindow(io, dec->last_row_, row, &rows_data, in_stride)) {
// Nothing to output (this time). // Nothing to output (this time).
} else { } else {
@ -1193,6 +1192,7 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
VP8LFillBitWindow(br); VP8LFillBitWindow(br);
dist_code = GetCopyDistance(dist_symbol, br); dist_code = GetCopyDistance(dist_symbol, br);
dist = PlaneCodeToDistance(width, dist_code); dist = PlaneCodeToDistance(width, dist_code);
if (VP8LIsEndOfStream(br)) break; if (VP8LIsEndOfStream(br)) break;
if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) { if (src - data < (ptrdiff_t)dist || src_end - src < (ptrdiff_t)length) {
goto Error; goto Error;
@ -1553,7 +1553,7 @@ static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
const int cache_pixs = width * num_rows_to_process; const int cache_pixs = width * num_rows_to_process;
uint8_t* const dst = output + width * cur_row; uint8_t* const dst = output + width * cur_row;
const uint32_t* const src = dec->argb_cache_; const uint32_t* const src = dec->argb_cache_;
ApplyInverseTransforms(dec, num_rows_to_process, in); ApplyInverseTransforms(dec, cur_row, num_rows_to_process, in);
WebPExtractGreen(src, dst, cache_pixs); WebPExtractGreen(src, dst, cache_pixs);
AlphaApplyFilter(alph_dec, AlphaApplyFilter(alph_dec,
cur_row, cur_row + num_rows_to_process, dst, width); cur_row, cur_row + num_rows_to_process, dst, width);

@ -37,7 +37,7 @@ struct VP8LTransform {
int bits_; // subsampling bits defining transform window. int bits_; // subsampling bits defining transform window.
int xsize_; // transform window X index. int xsize_; // transform window X index.
int ysize_; // transform window Y index. int ysize_; // transform window Y index.
uint32_t *data_; // transform data. uint32_t* data_; // transform data.
}; };
typedef struct { typedef struct {
@ -48,23 +48,23 @@ typedef struct {
int huffman_mask_; int huffman_mask_;
int huffman_subsample_bits_; int huffman_subsample_bits_;
int huffman_xsize_; int huffman_xsize_;
uint32_t *huffman_image_; uint32_t* huffman_image_;
int num_htree_groups_; int num_htree_groups_;
HTreeGroup *htree_groups_; HTreeGroup* htree_groups_;
HuffmanCode *huffman_tables_; HuffmanCode* huffman_tables_;
} VP8LMetadata; } VP8LMetadata;
typedef struct VP8LDecoder VP8LDecoder; typedef struct VP8LDecoder VP8LDecoder;
struct VP8LDecoder { struct VP8LDecoder {
VP8StatusCode status_; VP8StatusCode status_;
VP8LDecodeState state_; VP8LDecodeState state_;
VP8Io *io_; VP8Io* io_;
const WebPDecBuffer *output_; // shortcut to io->opaque->output const WebPDecBuffer* output_; // shortcut to io->opaque->output
uint32_t *pixels_; // Internal data: either uint8_t* for alpha uint32_t* pixels_; // Internal data: either uint8_t* for alpha
// or uint32_t* for BGRA. // or uint32_t* for BGRA.
uint32_t *argb_cache_; // Scratch buffer for temporary BGRA storage. uint32_t* argb_cache_; // Scratch buffer for temporary BGRA storage.
VP8LBitReader br_; VP8LBitReader br_;
int incremental_; // if true, incremental decoding is expected int incremental_; // if true, incremental decoding is expected
@ -86,8 +86,8 @@ struct VP8LDecoder {
// or'd bitset storing the transforms types. // or'd bitset storing the transforms types.
uint32_t transforms_seen_; uint32_t transforms_seen_;
uint8_t *rescaler_memory; // Working memory for rescaling work. uint8_t* rescaler_memory; // Working memory for rescaling work.
WebPRescaler *rescaler; // Common rescaler for all channels. WebPRescaler* rescaler; // Common rescaler for all channels.
}; };
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

@ -24,8 +24,8 @@
#include "src/webp/format_constants.h" #include "src/webp/format_constants.h"
#define DMUX_MAJ_VERSION 1 #define DMUX_MAJ_VERSION 1
#define DMUX_MIN_VERSION 0 #define DMUX_MIN_VERSION 1
#define DMUX_REV_VERSION 3 #define DMUX_REV_VERSION 0
typedef struct { typedef struct {
size_t start_; // start location of the data size_t start_; // start location of the data

@ -1361,7 +1361,8 @@ static void RD4_NEON(uint8_t* dst) { // Down-right
const uint32_t J = dst[-1 + 1 * BPS]; const uint32_t J = dst[-1 + 1 * BPS];
const uint32_t K = dst[-1 + 2 * BPS]; const uint32_t K = dst[-1 + 2 * BPS];
const uint32_t L = dst[-1 + 3 * BPS]; const uint32_t L = dst[-1 + 3 * BPS];
const uint64x1_t LKJI____ = vcreate_u64(L | (K << 8) | (J << 16) | (I << 24)); const uint64x1_t LKJI____ =
vcreate_u64((uint64_t)L | (K << 8) | (J << 16) | (I << 24));
const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC); const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC);
const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8)); const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8));
const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16)); const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16));
@ -1427,10 +1428,16 @@ static WEBP_INLINE void DC8_NEON(uint8_t* dst, int do_top, int do_left) {
if (do_top) { if (do_top) {
const uint8x8_t A = vld1_u8(dst - BPS); // top row const uint8x8_t A = vld1_u8(dst - BPS); // top row
#if defined(__aarch64__)
const uint16x8_t B = vmovl_u8(A);
const uint16_t p2 = vaddvq_u16(B);
sum_top = vdupq_n_u16(p2);
#else
const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
const uint16x4_t p1 = vpadd_u16(p0, p0); const uint16x4_t p1 = vpadd_u16(p0, p0);
const uint16x4_t p2 = vpadd_u16(p1, p1); const uint16x4_t p2 = vpadd_u16(p1, p1);
sum_top = vcombine_u16(p2, p2); sum_top = vcombine_u16(p2, p2);
#endif
} }
if (do_left) { if (do_left) {

@ -246,9 +246,9 @@ extern VP8Fdct VP8FTransform2; // performs two transforms at a time
extern VP8WHT VP8FTransformWHT; extern VP8WHT VP8FTransformWHT;
// Predictions // Predictions
// *dst is the destination block. *top and *left can be NULL. // *dst is the destination block. *top and *left can be NULL.
typedef void (*VP8IntraPreds)(uint8_t *dst, const uint8_t* left, typedef void (*VP8IntraPreds)(uint8_t* dst, const uint8_t* left,
const uint8_t* top); const uint8_t* top);
typedef void (*VP8Intra4Preds)(uint8_t *dst, const uint8_t* top); typedef void (*VP8Intra4Preds)(uint8_t* dst, const uint8_t* top);
extern VP8Intra4Preds VP8EncPredLuma4; extern VP8Intra4Preds VP8EncPredLuma4;
extern VP8IntraPreds VP8EncPredLuma16; extern VP8IntraPreds VP8EncPredLuma16;
extern VP8IntraPreds VP8EncPredChroma8; extern VP8IntraPreds VP8EncPredChroma8;

@ -81,7 +81,7 @@ static WEBP_INLINE uint32_t ClampedAddSubtractHalf(uint32_t c0, uint32_t c1,
// gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is // gcc <= 4.9 on ARM generates incorrect code in Select() when Sub3() is
// inlined. // inlined.
#if defined(__arm__) && LOCAL_GCC_VERSION <= 0x409 #if defined(__arm__) && defined(__GNUC__) && LOCAL_GCC_VERSION <= 0x409
# define LOCAL_INLINE __attribute__ ((noinline)) # define LOCAL_INLINE __attribute__ ((noinline))
#else #else
# define LOCAL_INLINE WEBP_INLINE # define LOCAL_INLINE WEBP_INLINE
@ -167,15 +167,20 @@ static uint32_t Predictor13_C(uint32_t left, const uint32_t* const top) {
return pred; return pred;
} }
GENERATE_PREDICTOR_ADD(Predictor0_C, PredictorAdd0_C) static void PredictorAdd0_C(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) {
int x;
(void)upper;
for (x = 0; x < num_pixels; ++x) out[x] = VP8LAddPixels(in[x], ARGB_BLACK);
}
static void PredictorAdd1_C(const uint32_t* in, const uint32_t* upper, static void PredictorAdd1_C(const uint32_t* in, const uint32_t* upper,
int num_pixels, uint32_t* out) { int num_pixels, uint32_t* out) {
int i; int i;
uint32_t left = out[-1]; uint32_t left = out[-1];
(void)upper;
for (i = 0; i < num_pixels; ++i) { for (i = 0; i < num_pixels; ++i) {
out[i] = left = VP8LAddPixels(in[i], left); out[i] = left = VP8LAddPixels(in[i], left);
} }
(void)upper;
} }
GENERATE_PREDICTOR_ADD(Predictor2_C, PredictorAdd2_C) GENERATE_PREDICTOR_ADD(Predictor2_C, PredictorAdd2_C)
GENERATE_PREDICTOR_ADD(Predictor3_C, PredictorAdd3_C) GENERATE_PREDICTOR_ADD(Predictor3_C, PredictorAdd3_C)

@ -177,6 +177,7 @@ uint32_t VP8LSubPixels(uint32_t a, uint32_t b) {
static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \ static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \ int num_pixels, uint32_t* out) { \
int x; \ int x; \
assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \ for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(out[x - 1], upper + x); \ const uint32_t pred = (PREDICTOR)(out[x - 1], upper + x); \
out[x] = VP8LAddPixels(in[x], pred); \ out[x] = VP8LAddPixels(in[x], pred); \
@ -189,6 +190,7 @@ static void PREDICTOR_ADD(const uint32_t* in, const uint32_t* upper, \
static void PREDICTOR_SUB(const uint32_t* in, const uint32_t* upper, \ static void PREDICTOR_SUB(const uint32_t* in, const uint32_t* upper, \
int num_pixels, uint32_t* out) { \ int num_pixels, uint32_t* out) { \
int x; \ int x; \
assert(upper != NULL); \
for (x = 0; x < num_pixels; ++x) { \ for (x = 0; x < num_pixels; ++x) { \
const uint32_t pred = (PREDICTOR)(in[x - 1], upper + x); \ const uint32_t pred = (PREDICTOR)(in[x - 1], upper + x); \
out[x] = VP8LSubPixels(in[x], pred); \ out[x] = VP8LSubPixels(in[x], pred); \

@ -455,8 +455,9 @@ static void PredictorSub0_SSE2(const uint32_t* in, const uint32_t* upper,
_mm_storeu_si128((__m128i*)&out[i], res); _mm_storeu_si128((__m128i*)&out[i], res);
} }
if (i != num_pixels) { if (i != num_pixels) {
VP8LPredictorsSub_C[0](in + i, upper + i, num_pixels - i, out + i); VP8LPredictorsSub_C[0](in + i, NULL, num_pixels - i, out + i);
} }
(void)upper;
} }
#define GENERATE_PREDICTOR_1(X, IN) \ #define GENERATE_PREDICTOR_1(X, IN) \

@ -191,8 +191,9 @@ static void PredictorAdd0_SSE2(const uint32_t* in, const uint32_t* upper,
_mm_storeu_si128((__m128i*)&out[i], res); _mm_storeu_si128((__m128i*)&out[i], res);
} }
if (i != num_pixels) { if (i != num_pixels) {
VP8LPredictorsAdd_C[0](in + i, upper + i, num_pixels - i, out + i); VP8LPredictorsAdd_C[0](in + i, NULL, num_pixels - i, out + i);
} }
(void)upper;
} }
// Predictor1: left. // Predictor1: left.

@ -576,9 +576,9 @@ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bot_y, \
const uint32_t l_uv = ((cur_u[0]) | ((cur_v[0]) << 16)); \ const uint32_t l_uv = ((cur_u[0]) | ((cur_v[0]) << 16)); \
const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \ const uint32_t uv0 = (3 * tl_uv + l_uv + 0x00020002u) >> 2; \
const uint8_t* ptop_y = &top_y[1]; \ const uint8_t* ptop_y = &top_y[1]; \
uint8_t *ptop_dst = top_dst + XSTEP; \ uint8_t* ptop_dst = top_dst + XSTEP; \
const uint8_t* pbot_y = &bot_y[1]; \ const uint8_t* pbot_y = &bot_y[1]; \
uint8_t *pbot_dst = bot_dst + XSTEP; \ uint8_t* pbot_dst = bot_dst + XSTEP; \
\ \
FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \ FUNC(top_y[0], uv0 & 0xff, (uv0 >> 16), top_dst); \
if (bot_y != NULL) { \ if (bot_y != NULL) { \

@ -58,8 +58,8 @@
} while (0) } while (0)
// Turn the macro into a function for reducing code-size when non-critical // Turn the macro into a function for reducing code-size when non-critical
static void Upsample16Pixels_NEON(const uint8_t *r1, const uint8_t *r2, static void Upsample16Pixels_NEON(const uint8_t* r1, const uint8_t* r2,
uint8_t *out) { uint8_t* out) {
UPSAMPLE_16PIXELS(r1, r2, out); UPSAMPLE_16PIXELS(r1, r2, out);
} }
@ -190,14 +190,14 @@ static const int16_t kCoeffs1[4] = { 19077, 26149, 6419, 13320 };
} }
#define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \ #define NEON_UPSAMPLE_FUNC(FUNC_NAME, FMT, XSTEP) \
static void FUNC_NAME(const uint8_t *top_y, const uint8_t *bottom_y, \ static void FUNC_NAME(const uint8_t* top_y, const uint8_t* bottom_y, \
const uint8_t *top_u, const uint8_t *top_v, \ const uint8_t* top_u, const uint8_t* top_v, \
const uint8_t *cur_u, const uint8_t *cur_v, \ const uint8_t* cur_u, const uint8_t* cur_v, \
uint8_t *top_dst, uint8_t *bottom_dst, int len) { \ uint8_t* top_dst, uint8_t* bottom_dst, int len) { \
int block; \ int block; \
/* 16 byte aligned array to cache reconstructed u and v */ \ /* 16 byte aligned array to cache reconstructed u and v */ \
uint8_t uv_buf[2 * 32 + 15]; \ uint8_t uv_buf[2 * 32 + 15]; \
uint8_t *const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \ uint8_t* const r_uv = (uint8_t*)((uintptr_t)(uv_buf + 15) & ~15); \
const int uv_len = (len + 1) >> 1; \ const int uv_len = (len + 1) >> 1; \
/* 9 pixels must be read-able for each block */ \ /* 9 pixels must be read-able for each block */ \
const int num_blocks = (uv_len - 1) >> 3; \ const int num_blocks = (uv_len - 1) >> 3; \

@ -641,7 +641,7 @@ static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo,
// Merges some histograms with same bin_id together if it's advantageous. // Merges some histograms with same bin_id together if it's advantageous.
// Sets the remaining histograms to NULL. // Sets the remaining histograms to NULL.
static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo, static void HistogramCombineEntropyBin(VP8LHistogramSet* const image_histo,
int *num_used, int* num_used,
const uint16_t* const clusters, const uint16_t* const clusters,
uint16_t* const cluster_mappings, uint16_t* const cluster_mappings,
VP8LHistogram* cur_combo, VP8LHistogram* cur_combo,

@ -29,11 +29,15 @@
#define USE_INVERSE_ALPHA_TABLE #define USE_INVERSE_ALPHA_TABLE
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
#define ALPHA_OFFSET 0 // uint32_t 0xff000000 is 0xff,00,00,00 in memory // uint32_t 0xff000000 is 0xff,00,00,00 in memory
#define CHANNEL_OFFSET(i) (i)
#else #else
#define ALPHA_OFFSET 3 // uint32_t 0xff000000 is 0x00,00,00,ff in memory // uint32_t 0xff000000 is 0x00,00,00,ff in memory
#define CHANNEL_OFFSET(i) (3-(i))
#endif #endif
#define ALPHA_OFFSET CHANNEL_OFFSET(0)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Detection of non-trivial transparency // Detection of non-trivial transparency
@ -997,10 +1001,10 @@ static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace,
return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
} else { } else {
const uint8_t* const argb = (const uint8_t*)picture->argb; const uint8_t* const argb = (const uint8_t*)picture->argb;
const uint8_t* const a = argb + (0 ^ ALPHA_OFFSET); const uint8_t* const a = argb + CHANNEL_OFFSET(0);
const uint8_t* const r = argb + (1 ^ ALPHA_OFFSET); const uint8_t* const r = argb + CHANNEL_OFFSET(1);
const uint8_t* const g = argb + (2 ^ ALPHA_OFFSET); const uint8_t* const g = argb + CHANNEL_OFFSET(2);
const uint8_t* const b = argb + (3 ^ ALPHA_OFFSET); const uint8_t* const b = argb + CHANNEL_OFFSET(3);
picture->colorspace = WEBP_YUV420; picture->colorspace = WEBP_YUV420;
return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride, return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride,
@ -1050,7 +1054,7 @@ int WebPPictureYUVAToARGB(WebPPicture* picture) {
const int height = picture->height; const int height = picture->height;
const int argb_stride = 4 * picture->argb_stride; const int argb_stride = 4 * picture->argb_stride;
uint8_t* dst = (uint8_t*)picture->argb; uint8_t* dst = (uint8_t*)picture->argb;
const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y; const uint8_t* cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
WebPUpsampleLinePairFunc upsample = WebPUpsampleLinePairFunc upsample =
WebPGetLinePairConverter(ALPHA_OFFSET > 0); WebPGetLinePairConverter(ALPHA_OFFSET > 0);

@ -31,8 +31,8 @@ extern "C" {
// version numbers // version numbers
#define ENC_MAJ_VERSION 1 #define ENC_MAJ_VERSION 1
#define ENC_MIN_VERSION 0 #define ENC_MIN_VERSION 1
#define ENC_REV_VERSION 3 #define ENC_REV_VERSION 0
enum { MAX_LF_LEVELS = 64, // Maximum loop filter level enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
@ -249,7 +249,7 @@ typedef struct {
int percent0_; // saved initial progress percent int percent0_; // saved initial progress percent
DError left_derr_; // left error diffusion (u/v) DError left_derr_; // left error diffusion (u/v)
DError *top_derr_; // top diffusion error - NULL if disabled DError* top_derr_; // top diffusion error - NULL if disabled
uint8_t* y_left_; // left luma samples (addressable from index -1 to 15). uint8_t* y_left_; // left luma samples (addressable from index -1 to 15).
uint8_t* u_left_; // left u samples (addressable from index -1 to 7) uint8_t* u_left_; // left u samples (addressable from index -1 to 7)

@ -28,8 +28,8 @@ extern "C" {
// Defines and constants. // Defines and constants.
#define MUX_MAJ_VERSION 1 #define MUX_MAJ_VERSION 1
#define MUX_MIN_VERSION 0 #define MUX_MIN_VERSION 1
#define MUX_REV_VERSION 3 #define MUX_REV_VERSION 0
// Chunk object. // Chunk object.
typedef struct WebPChunk WebPChunk; typedef struct WebPChunk WebPChunk;

@ -100,7 +100,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
WebPMuxImage* const wpi) { WebPMuxImage* const wpi) {
const uint8_t* bytes = chunk->data_.bytes; const uint8_t* bytes = chunk->data_.bytes;
size_t size = chunk->data_.size; size_t size = chunk->data_.size;
const uint8_t* const last = bytes + size; const uint8_t* const last = (bytes == NULL) ? NULL : bytes + size;
WebPChunk subchunk; WebPChunk subchunk;
size_t subchunk_size; size_t subchunk_size;
WebPChunk** unknown_chunk_list = &wpi->unknown_; WebPChunk** unknown_chunk_list = &wpi->unknown_;

@ -26,7 +26,7 @@ extern "C" {
// Main color cache struct. // Main color cache struct.
typedef struct { typedef struct {
uint32_t *colors_; // color entries uint32_t* colors_; // color entries
int hash_shift_; // Hash shift: 32 - hash_bits_. int hash_shift_; // Hash shift: 32 - hash_bits_.
int hash_bits_; int hash_bits_;
} VP8LColorCache; } VP8LColorCache;

@ -73,7 +73,7 @@ typedef struct {
#endif #endif
static int pthread_create(pthread_t* const thread, const void* attr, static int pthread_create(pthread_t* const thread, const void* attr,
unsigned int (__stdcall *start)(void*), void* arg) { unsigned int (__stdcall* start)(void*), void* arg) {
(void)attr; (void)attr;
#ifdef USE_CREATE_THREAD #ifdef USE_CREATE_THREAD
*thread = CreateThread(NULL, /* lpThreadAttributes */ *thread = CreateThread(NULL, /* lpThreadAttributes */

@ -216,9 +216,14 @@ void WebPSafeFree(void* const ptr) {
free(ptr); free(ptr);
} }
// Public API function. // Public API functions.
void* WebPMalloc(size_t size) {
return WebPSafeMalloc(1, size);
}
void WebPFree(void* ptr) { void WebPFree(void* ptr) {
free(ptr); WebPSafeFree(ptr);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

@ -20,7 +20,7 @@
extern "C" { extern "C" {
#endif #endif
#define WEBP_DECODER_ABI_VERSION 0x0208 // MAJOR(8b) + MINOR(8b) #define WEBP_DECODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b)
// Note: forward declaring enumerations is not allowed in (strict) C and C++, // Note: forward declaring enumerations is not allowed in (strict) C and C++,
// the types are left here for reference. // the types are left here for reference.
@ -91,9 +91,6 @@ WEBP_EXTERN uint8_t* WebPDecodeYUV(const uint8_t* data, size_t data_size,
uint8_t** u, uint8_t** v, uint8_t** u, uint8_t** v,
int* stride, int* uv_stride); int* stride, int* uv_stride);
// Releases memory returned by the WebPDecode*() functions above.
WEBP_EXTERN void WebPFree(void* ptr);
// These five functions are variants of the above ones, that decode the image // These five functions are variants of the above ones, that decode the image
// directly into a pre-allocated buffer 'output_buffer'. The maximum storage // directly into a pre-allocated buffer 'output_buffer'. The maximum storage
// available in this buffer is indicated by 'output_buffer_size'. If this // available in this buffer is indicated by 'output_buffer_size'. If this

@ -20,7 +20,7 @@
extern "C" { extern "C" {
#endif #endif
#define WEBP_ENCODER_ABI_VERSION 0x020e // MAJOR(8b) + MINOR(8b) #define WEBP_ENCODER_ABI_VERSION 0x020f // MAJOR(8b) + MINOR(8b)
// Note: forward declaring enumerations is not allowed in (strict) C and C++, // Note: forward declaring enumerations is not allowed in (strict) C and C++,
// the types are left here for reference. // the types are left here for reference.
@ -79,9 +79,6 @@ WEBP_EXTERN size_t WebPEncodeLosslessBGRA(const uint8_t* bgra,
int width, int height, int stride, int width, int height, int stride,
uint8_t** output); uint8_t** output);
// Releases memory returned by the WebPEncode*() functions above.
WEBP_EXTERN void WebPFree(void* ptr);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Coding parameters // Coding parameters
@ -306,7 +303,7 @@ struct WebPPicture {
// YUV input (mostly used for input to lossy compression) // YUV input (mostly used for input to lossy compression)
WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr). WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr).
int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION) int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION)
uint8_t *y, *u, *v; // pointers to luma/chroma planes. uint8_t* y, *u, *v; // pointers to luma/chroma planes.
int y_stride, uv_stride; // luma/chroma strides. int y_stride, uv_stride; // luma/chroma strides.
uint8_t* a; // pointer to the alpha plane uint8_t* a; // pointer to the alpha plane
int a_stride; // stride of the alpha plane int a_stride; // stride of the alpha plane
@ -350,7 +347,7 @@ struct WebPPicture {
uint32_t pad3[3]; // padding for later use uint32_t pad3[3]; // padding for later use
// Unused for now // Unused for now
uint8_t *pad4, *pad5; uint8_t* pad4, *pad5;
uint32_t pad6[8]; // padding for later use uint32_t pad6[8]; // padding for later use
// PRIVATE FIELDS // PRIVATE FIELDS

@ -57,7 +57,7 @@ extern "C" {
WebPMuxGetChunk(mux, "ICCP", &icc_profile); WebPMuxGetChunk(mux, "ICCP", &icc_profile);
// ... (Consume icc_data). // ... (Consume icc_data).
WebPMuxDelete(mux); WebPMuxDelete(mux);
free(data); WebPFree(data);
*/ */
// Note: forward declaring enumerations is not allowed in (strict) C and C++, // Note: forward declaring enumerations is not allowed in (strict) C and C++,
@ -245,7 +245,7 @@ WEBP_EXTERN WebPMuxError WebPMuxPushFrame(
WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data); WebPMux* mux, const WebPMuxFrameInfo* frame, int copy_data);
// Gets the nth frame from the mux object. // Gets the nth frame from the mux object.
// The content of 'frame->bitstream' is allocated using malloc(), and NOT // The content of 'frame->bitstream' is allocated using WebPMalloc(), and NOT
// owned by the 'mux' object. It MUST be deallocated by the caller by calling // owned by the 'mux' object. It MUST be deallocated by the caller by calling
// WebPDataClear(). // WebPDataClear().
// nth=0 has a special meaning - last position. // nth=0 has a special meaning - last position.
@ -376,10 +376,10 @@ WEBP_EXTERN WebPMuxError WebPMuxNumChunks(const WebPMux* mux,
// Assembles all chunks in WebP RIFF format and returns in 'assembled_data'. // Assembles all chunks in WebP RIFF format and returns in 'assembled_data'.
// This function also validates the mux object. // This function also validates the mux object.
// Note: The content of 'assembled_data' will be ignored and overwritten. // Note: The content of 'assembled_data' will be ignored and overwritten.
// Also, the content of 'assembled_data' is allocated using malloc(), and NOT // Also, the content of 'assembled_data' is allocated using WebPMalloc(), and
// owned by the 'mux' object. It MUST be deallocated by the caller by calling // NOT owned by the 'mux' object. It MUST be deallocated by the caller by
// WebPDataClear(). It's always safe to call WebPDataClear() upon return, // calling WebPDataClear(). It's always safe to call WebPDataClear() upon
// even in case of error. // return, even in case of error.
// Parameters: // Parameters:
// mux - (in/out) object whose chunks are to be assembled // mux - (in/out) object whose chunks are to be assembled
// assembled_data - (out) assembled WebP data // assembled_data - (out) assembled WebP data

@ -14,7 +14,6 @@
#ifndef WEBP_WEBP_MUX_TYPES_H_ #ifndef WEBP_WEBP_MUX_TYPES_H_
#define WEBP_WEBP_MUX_TYPES_H_ #define WEBP_WEBP_MUX_TYPES_H_
#include <stdlib.h> // free()
#include <string.h> // memset() #include <string.h> // memset()
#include "./types.h" #include "./types.h"
@ -56,6 +55,7 @@ typedef enum WebPMuxAnimBlend {
// Data type used to describe 'raw' data, e.g., chunk data // Data type used to describe 'raw' data, e.g., chunk data
// (ICC profile, metadata) and WebP compressed image data. // (ICC profile, metadata) and WebP compressed image data.
// 'bytes' memory must be allocated using WebPMalloc() and such.
struct WebPData { struct WebPData {
const uint8_t* bytes; const uint8_t* bytes;
size_t size; size_t size;
@ -68,11 +68,11 @@ static WEBP_INLINE void WebPDataInit(WebPData* webp_data) {
} }
} }
// Clears the contents of the 'webp_data' object by calling free(). Does not // Clears the contents of the 'webp_data' object by calling WebPFree().
// deallocate the object itself. // Does not deallocate the object itself.
static WEBP_INLINE void WebPDataClear(WebPData* webp_data) { static WEBP_INLINE void WebPDataClear(WebPData* webp_data) {
if (webp_data != NULL) { if (webp_data != NULL) {
free((void*)webp_data->bytes); WebPFree((void*)webp_data->bytes);
WebPDataInit(webp_data); WebPDataInit(webp_data);
} }
} }
@ -83,7 +83,7 @@ static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {
if (src == NULL || dst == NULL) return 0; if (src == NULL || dst == NULL) return 0;
WebPDataInit(dst); WebPDataInit(dst);
if (src->bytes != NULL && src->size != 0) { if (src->bytes != NULL && src->size != 0) {
dst->bytes = (uint8_t*)malloc(src->size); dst->bytes = (uint8_t*)WebPMalloc(src->size);
if (dst->bytes == NULL) return 0; if (dst->bytes == NULL) return 0;
memcpy((void*)dst->bytes, src->bytes, src->size); memcpy((void*)dst->bytes, src->bytes, src->size);
dst->size = src->size; dst->size = src->size;

@ -7,7 +7,7 @@
// be found in the AUTHORS file in the root of the source tree. // be found in the AUTHORS file in the root of the source tree.
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// //
// Common types // Common types + memory wrappers
// //
// Author: Skal (pascal.massimino@gmail.com) // Author: Skal (pascal.massimino@gmail.com)
@ -49,4 +49,20 @@ typedef long long int int64_t;
// Macro to check ABI compatibility (same major revision number) // Macro to check ABI compatibility (same major revision number)
#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8)) #define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8))
#ifdef __cplusplus
extern "C" {
#endif
// Allocates 'size' bytes of memory. Returns NULL upon error. Memory
// must be deallocated by calling WebPFree(). This function is made available
// by the core 'libwebp' library.
WEBP_EXTERN void* WebPMalloc(size_t size);
// Releases memory returned by the WebPDecode*() functions (from decode.h).
WEBP_EXTERN void WebPFree(void* ptr);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WEBP_WEBP_TYPES_H_ #endif // WEBP_WEBP_TYPES_H_

@ -1,15 +1,15 @@
#Cross compile TBB from source #Cross compile TBB from source
project(tbb) project(tbb CXX)
if (WIN32 AND NOT ARM) if (WIN32 AND NOT ARM)
message(FATAL_ERROR "BUILD_TBB option supports Windows on ARM only!\nUse regular official TBB build instead of the BUILD_TBB option!") message(FATAL_ERROR "BUILD_TBB option supports Windows on ARM only!\nUse regular official TBB build instead of the BUILD_TBB option!")
endif() endif()
ocv_update(OPENCV_TBB_RELEASE "v2020.0") ocv_update(OPENCV_TBB_RELEASE "v2020.1")
ocv_update(OPENCV_TBB_RELEASE_MD5 "5858dd01ec007c139d5d178b21e06dae") ocv_update(OPENCV_TBB_RELEASE_MD5 "734f335d06ee80a7d4a20cc0da734c59")
ocv_update(OPENCV_TBB_FILENAME "${OPENCV_TBB_RELEASE}.tar.gz") ocv_update(OPENCV_TBB_FILENAME "${OPENCV_TBB_RELEASE}.tar.gz")
string(REGEX REPLACE "^v" "" OPENCV_TBB_RELEASE_ "${OPENCV_TBB_RELEASE}") string(REGEX REPLACE "^v" "" OPENCV_TBB_RELEASE_ "${OPENCV_TBB_RELEASE}")
ocv_update(OPENCV_TBB_SUBDIR "tbb-${OPENCV_TBB_RELEASE_}") #ocv_update(OPENCV_TBB_SUBDIR ...)
set(tbb_src_dir "${OpenCV_BINARY_DIR}/3rdparty/tbb") set(tbb_src_dir "${OpenCV_BINARY_DIR}/3rdparty/tbb")
ocv_download(FILENAME ${OPENCV_TBB_FILENAME} ocv_download(FILENAME ${OPENCV_TBB_FILENAME}
@ -25,6 +25,16 @@ ocv_download(FILENAME ${OPENCV_TBB_FILENAME}
if(NOT res) if(NOT res)
return() return()
endif() endif()
if(OPENCV_TBB_SUBDIR)
# use current value
ocv_assert(EXISTS "${tbb_src_dir}/${OPENCV_TBB_SUBDIR}")
elseif(EXISTS "${tbb_src_dir}/oneTBB-${OPENCV_TBB_RELEASE_}")
set(OPENCV_TBB_SUBDIR "oneTBB-${OPENCV_TBB_RELEASE_}")
elseif(EXISTS "${tbb_src_dir}/tbb-${OPENCV_TBB_RELEASE_}")
set(OPENCV_TBB_SUBDIR "oneTBB-${OPENCV_TBB_RELEASE_}")
else()
message(FATAL_ERROR "TBB: Can't configure TBB. Specify OPENCV_TBB_SUBDIR through command-line.")
endif()
set(tbb_src_dir "${tbb_src_dir}/${OPENCV_TBB_SUBDIR}") set(tbb_src_dir "${tbb_src_dir}/${OPENCV_TBB_SUBDIR}")
ocv_include_directories("${tbb_src_dir}/include" ocv_include_directories("${tbb_src_dir}/include"
@ -36,11 +46,11 @@ file(GLOB lib_srcs "${tbb_src_dir}/src/tbb/*.cpp")
file(GLOB lib_hdrs "${tbb_src_dir}/src/tbb/*.h") file(GLOB lib_hdrs "${tbb_src_dir}/src/tbb/*.h")
list(APPEND lib_srcs "${tbb_src_dir}/src/rml/client/rml_tbb.cpp") list(APPEND lib_srcs "${tbb_src_dir}/src/rml/client/rml_tbb.cpp")
ocv_list_filterout(lib_srcs "${tbb_src_dir}/src/tbb/tbbbind.cpp") # hwloc.h requirement ocv_list_filterout(lib_srcs "${tbb_src_dir}/src/tbb/tbbbind.cpp") # hwloc.h requirement
ocv_list_filterout(lib_srcs "${tbb_src_dir}/src/tbb/tbb_bind.cpp") # hwloc.h requirement 2020.1+
if (WIN32) if (WIN32)
add_definitions(/D__TBB_DYNAMIC_LOAD_ENABLED=0 add_definitions(/D__TBB_DYNAMIC_LOAD_ENABLED=0
/D__TBB_BUILD=1 /D__TBB_BUILD=1
/DTBB_SUPPRESS_DEPRECATED_MESSAGES=1
/DTBB_NO_LEGACY=1 /DTBB_NO_LEGACY=1
/D_UNICODE /D_UNICODE
/DUNICODE /DUNICODE
@ -99,7 +109,11 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${tbb_version_file}.cmakein" "${CMAK
list(APPEND TBB_SOURCE_FILES "${CMAKE_CURRENT_BINARY_DIR}/${tbb_version_file}") list(APPEND TBB_SOURCE_FILES "${CMAKE_CURRENT_BINARY_DIR}/${tbb_version_file}")
add_library(tbb ${TBB_SOURCE_FILES}) add_library(tbb ${TBB_SOURCE_FILES})
target_compile_definitions(tbb PUBLIC TBB_USE_GCC_BUILTINS=1 __TBB_GCC_BUILTIN_ATOMICS_PRESENT=1) target_compile_definitions(tbb PUBLIC
TBB_USE_GCC_BUILTINS=1
__TBB_GCC_BUILTIN_ATOMICS_PRESENT=1
TBB_SUPPRESS_DEPRECATED_MESSAGES=1
)
target_include_directories(tbb SYSTEM PUBLIC $<BUILD_INTERFACE:${tbb_src_dir}/include> target_include_directories(tbb SYSTEM PUBLIC $<BUILD_INTERFACE:${tbb_src_dir}/include>
PRIVATE "${CMAKE_CURRENT_BINARY_DIR}" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}"
) )

@ -653,6 +653,7 @@ bool dls::is_empty(const cv::Mat * M)
bool dls::positive_eigenvalues(const cv::Mat * eigenvalues) bool dls::positive_eigenvalues(const cv::Mat * eigenvalues)
{ {
CV_Assert(eigenvalues && !eigenvalues->empty());
cv::MatConstIterator_<double> it = eigenvalues->begin<double>(); cv::MatConstIterator_<double> it = eigenvalues->begin<double>();
return *(it) > 0 && *(it+1) > 0 && *(it+2) > 0; return *(it) > 0 && *(it+1) > 0 && *(it+2) > 0;
} }

Loading…
Cancel
Save