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

This commit is contained in:
Alexander Alekhin 2020-03-24 11:12:11 +00:00
commit ef395c3866
54 changed files with 509 additions and 274 deletions

View File

@ -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")

View File

@ -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.

View File

@ -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) { \

View File

@ -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. */

View File

@ -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

View File

@ -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;

View File

@ -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); \

View File

@ -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++;

View File

@ -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.

View File

@ -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:

View File

@ -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.

View File

@ -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()

View File

@ -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);

View File

@ -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 */

View File

@ -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. */

View File

@ -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;

View File

@ -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,45 +5837,105 @@ 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) {
/* /*
* Unable to allocate new strip information, give up and use * Replace a file with contiguous strips > 2 GB of uncompressed data by
* the original one strip information. * multiple smaller strips. This is useful for
* 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
* 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); /* Check that the strips are contiguous and of the expected size */
_TIFFfree(td->td_stripoffset); for( i = 0; i < td->td_nstrips; i++ )
td->td_stripbytecount = newcounts; {
td->td_stripoffset = newoffsets; if( i == td->td_nstrips - 1 )
td->td_stripbytecountsorted = 1; {
if( td->td_stripbytecount[i] < TIFFVStripSize64(
tif, td->td_imagelength - i * td->td_rowsperstrip ) )
{
return;
} }
}
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;
}
}
}
/* Aim for 512 MB strips (that will still be manageable by 32 bit builds */
rowblocksperstrip = (uint32) (512 * 1024 * 1024 / rowblockbytes);
if( rowblocksperstrip == 0 )
rowblocksperstrip = 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 )
{ {

View File

@ -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)

View File

@ -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

View File

@ -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));
} }

View File

@ -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",

View File

@ -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);

View File

@ -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,8 +363,12 @@ TWebPSetupEncode(TIFF* tif)
return 0; return 0;
} }
// WebPConfigInitInternal above sets lossless to false
#if WEBP_ENCODER_ABI_VERSION >= 0x0100 #if WEBP_ENCODER_ABI_VERSION >= 0x0100
sp->sEncoderConfig.lossless = sp->lossless; sp->sEncoderConfig.lossless = sp->lossless;
if (sp->lossless) {
sp->sPicture.use_argb = 1;
}
#endif #endif
if (!WebPValidateConfig(&sp->sEncoderConfig)) { if (!WebPValidateConfig(&sp->sEncoderConfig)) {
@ -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,

View File

@ -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:

View File

@ -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,

View File

@ -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.

View File

@ -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!

View File

@ -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),

View File

@ -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);

View File

@ -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

View File

@ -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) {

View File

@ -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)

View File

@ -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); \

View File

@ -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) \

View File

@ -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.

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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_;

View File

@ -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);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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_

View File

@ -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}"
) )

View File

@ -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;
} }